public void Test_ProgressStream() { int count = 0; try { using (MemoryStream memoryStream = new MemoryStream(new byte[4096 * 10])) using (ProgressStream progressStream = new ProgressStream( memoryStream, (object sender, long readSize, long writeSize, out bool isStop) => { count++; if (readSize >= 8192) { isStop = true; } else { isStop = false; } }, 4096)) { byte[] tbyte = new byte[4096]; for (int i = 0; i < 4; i++) { progressStream.Read(tbyte, 0, tbyte.Length); } } } catch (StopIoException) { Assert.AreEqual(count, 2, "ProgressStream"); } }
private void EncodeThread() { for (;;) { Thread.Sleep(1000 * 1); if (this.EncodeState == ManagerState.Stop) return; UploadItem item = null; try { lock (_thisLock) { if (_settings.UploadItems.Count > 0) { item = _settings.UploadItems .Where(n => n.State == UploadState.ComputeHash || n.State == UploadState.Encoding || n.State == UploadState.ParityEncoding) .Where(n => n.Priority != 0) .OrderBy(n => -n.Priority) .Where(n => !_workingPaths.Contains(n.FilePath)) .FirstOrDefault(); if (item != null) { _workingPaths.Add(item.FilePath); } } } } catch (Exception) { return; } if (item == null) continue; try { if (item.Groups.Count == 0 && item.Keys.Count == 0) { if (item.Type == UploadType.Upload) { item.State = UploadState.Encoding; KeyCollection keys = null; byte[] cryptoKey = null; try { using (var stream = new UnbufferedFileStream(item.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read, FileOptions.None, _bufferManager)) using (ProgressStream hashProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) => { isStop = (this.EncodeState == ManagerState.Stop || !_settings.UploadItems.Contains(item)); item.EncodeOffset = Math.Min(readSize, stream.Length); }, 1024 * 1024, true)) using (ProgressStream encodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) => { isStop = (this.EncodeState == ManagerState.Stop || !_settings.UploadItems.Contains(item)); item.EncodeOffset = Math.Min(readSize, stream.Length); }, 1024 * 1024, true)) { if (stream.Length == 0) throw new InvalidOperationException("Stream Length"); item.Length = stream.Length; item.EncodeLength = stream.Length; item.State = UploadState.ComputeHash; if (item.HashAlgorithm == HashAlgorithm.Sha256) { cryptoKey = Sha256.ComputeHash(hashProgressStream); } stream.Seek(0, SeekOrigin.Begin); item.EncodeOffset = 0; item.State = UploadState.Encoding; keys = _cacheManager.Encoding(encodingProgressStream, item.CompressionAlgorithm, item.CryptoAlgorithm, cryptoKey, item.BlockLength, item.HashAlgorithm); } } catch (StopIoException) { continue; } lock (_thisLock) { if (!_settings.UploadItems.Contains(item)) { foreach (var key in keys) { _cacheManager.Unlock(key); } continue; } foreach (var key in keys) { item.UploadKeys.Add(key); item.LockedKeys.Add(key); } item.EncodeOffset = 0; item.EncodeLength = 0; item.CryptoKey = cryptoKey; item.Keys.AddRange(keys); } } else if (item.Type == UploadType.Share) { item.State = UploadState.ComputeHash; KeyCollection keys = null; try { using (var stream = new UnbufferedFileStream(item.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read, FileOptions.None, _bufferManager)) using (ProgressStream hashProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) => { isStop = (this.EncodeState == ManagerState.Stop || !_settings.UploadItems.Contains(item)); item.EncodeOffset = Math.Min(readSize, stream.Length); }, 1024 * 1024, true)) { if (stream.Length == 0) throw new InvalidOperationException("Stream Length"); item.Length = stream.Length; item.EncodeLength = stream.Length; keys = _cacheManager.Share(hashProgressStream, stream.Name, item.HashAlgorithm, item.BlockLength); } } catch (StopIoException) { continue; } if (keys.Count == 1) { lock (_thisLock) { if (!_settings.UploadItems.Contains(item)) { foreach (var key in keys) { _cacheManager.Unlock(key); } continue; } item.EncodeOffset = 0; item.EncodeLength = 0; item.UploadKeys.Add(keys[0]); item.Keys.Add(keys[0]); item.State = UploadState.Encoding; } } else { var groups = new List<Group>(); for (int i = 0, remain = keys.Count; 0 < remain; i++, remain -= 256) { var tempKeys = keys.GetRange(i * 256, Math.Min(remain, 256)); var group = new Group(); group.CorrectionAlgorithm = CorrectionAlgorithm.None; group.InformationLength = tempKeys.Count; group.BlockLength = item.BlockLength; group.Length = tempKeys.Sum(n => (long)_cacheManager.GetLength(n)); group.Keys.AddRange(tempKeys); groups.Add(group); } lock (_thisLock) { if (!_settings.UploadItems.Contains(item)) { foreach (var key in keys) { _cacheManager.Unlock(key); } continue; } item.EncodeOffset = 0; item.EncodeLength = 0; foreach (var key in keys) { item.UploadKeys.Add(key); } item.Groups.AddRange(groups); item.State = UploadState.Encoding; } } } } else if (item.Groups.Count == 0 && item.Keys.Count == 1) { lock (_thisLock) { if (!_settings.UploadItems.Contains(item)) continue; Metadata metadata = null; { if (item.Type == UploadType.Upload) { metadata = new Metadata(item.Depth, item.Keys[0], item.CompressionAlgorithm, item.CryptoAlgorithm, item.CryptoKey); } else if (item.Type == UploadType.Share) { if (item.Depth == 1) { metadata = new Metadata(item.Depth, item.Keys[0], CompressionAlgorithm.None, CryptoAlgorithm.None, null); } else { metadata = new Metadata(item.Depth, item.Keys[0], item.CompressionAlgorithm, item.CryptoAlgorithm, item.CryptoKey); } } item.Keys.Clear(); } item.Seed = new Seed(metadata); item.Seed.Name = item.Name; item.Seed.Length = item.Length; item.Seed.CreationTime = item.CreationTime; item.Seed.Keywords.AddRange(item.Keywords); if (item.DigitalSignature != null) { item.Seed.CreateCertificate(item.DigitalSignature); } foreach (var key in item.UploadKeys) { _connectionsManager.Upload(key); } { if (item.Type == UploadType.Upload) { _cacheManager.SetSeed(item.Seed.Clone(), item.RetainKeys.ToArray()); } else if (item.Type == UploadType.Share) { _cacheManager.SetSeed(item.Seed.Clone(), item.FilePath, item.RetainKeys.ToArray()); } item.RetainKeys.Clear(); } foreach (var key in item.LockedKeys) { _cacheManager.Unlock(key); } item.LockedKeys.Clear(); item.State = UploadState.Uploading; this.CheckState(item); } } else if (item.Keys.Count > 0) { item.State = UploadState.ParityEncoding; item.EncodeLength = item.Groups.Sum(n => { long sumLength = 0; for (int i = 0; i < n.InformationLength; i++) { if (_cacheManager.Contains(n.Keys[i])) { sumLength += (long)_cacheManager.GetLength(n.Keys[i]); } } return sumLength; }) + item.Keys.Sum(n => { if (_cacheManager.Contains(n)) { return (long)_cacheManager.GetLength(n); } return 0; }); var length = Math.Min(item.Keys.Count, 128); var keys = new KeyCollection(item.Keys.Take(length)); Group group = null; try { using (var tokenSource = new CancellationTokenSource()) { var task = _cacheManager.ParityEncoding(keys, item.HashAlgorithm, item.BlockLength, item.CorrectionAlgorithm, tokenSource.Token); while (!task.IsCompleted) { if ((this.EncodeState == ManagerState.Stop || !_settings.UploadItems.Contains(item))) tokenSource.Cancel(); Thread.Sleep(1000); } group = task.Result; } } catch (Exception) { continue; } lock (_thisLock) { if (!_settings.UploadItems.Contains(item)) { foreach (var key in group.Keys.Skip(group.InformationLength)) { _cacheManager.Unlock(key); } continue; } foreach (var key in group.Keys.Skip(group.InformationLength)) { item.UploadKeys.Add(key); item.LockedKeys.Add(key); } foreach (var key in group.Keys.Skip(group.Keys.Count - group.InformationLength)) { item.RetainKeys.Add(key); } item.Groups.Add(group); item.EncodeOffset = item.Groups.Sum(n => { long sumLength = 0; for (int i = 0; i < n.InformationLength; i++) { if (_cacheManager.Contains(n.Keys[i])) { sumLength += (long)_cacheManager.GetLength(n.Keys[i]); } } return sumLength; }); item.Keys.RemoveRange(0, length); } } else if (item.Groups.Count > 0 && item.Keys.Count == 0) { item.State = UploadState.Encoding; var index = new Index(); if (item.Type == UploadType.Upload) { index.Groups.AddRange(item.Groups); index.CompressionAlgorithm = item.CompressionAlgorithm; index.CryptoAlgorithm = item.CryptoAlgorithm; index.CryptoKey = item.CryptoKey; } else if (item.Type == UploadType.Share) { index.Groups.AddRange(item.Groups); if (item.Depth != 1) { index.CompressionAlgorithm = item.CompressionAlgorithm; index.CryptoAlgorithm = item.CryptoAlgorithm; index.CryptoKey = item.CryptoKey; } } byte[] cryptoKey = null; KeyCollection keys = null; try { using (var stream = index.Export(_bufferManager)) using (ProgressStream hashProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) => { isStop = (this.EncodeState == ManagerState.Stop || !_settings.UploadItems.Contains(item)); item.EncodeOffset = Math.Min(readSize, stream.Length); }, 1024 * 1024, true)) using (ProgressStream encodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) => { isStop = (this.EncodeState == ManagerState.Stop || !_settings.UploadItems.Contains(item)); item.EncodeOffset = Math.Min(readSize, stream.Length); }, 1024 * 1024, true)) { item.EncodeLength = stream.Length; item.State = UploadState.ComputeHash; if (item.HashAlgorithm == HashAlgorithm.Sha256) { cryptoKey = Sha256.ComputeHash(hashProgressStream); } stream.Seek(0, SeekOrigin.Begin); item.EncodeOffset = 0; item.State = UploadState.Encoding; keys = _cacheManager.Encoding(encodingProgressStream, item.CompressionAlgorithm, item.CryptoAlgorithm, cryptoKey, item.BlockLength, item.HashAlgorithm); } } catch (StopIoException) { continue; } lock (_thisLock) { if (!_settings.UploadItems.Contains(item)) { foreach (var key in keys) { _cacheManager.Unlock(key); } continue; } foreach (var key in keys) { item.UploadKeys.Add(key); item.LockedKeys.Add(key); } item.EncodeOffset = 0; item.EncodeLength = 0; item.CryptoKey = cryptoKey; item.Keys.AddRange(keys); item.Depth++; item.Groups.Clear(); } } } catch (Exception e) { item.State = UploadState.Error; Log.Error(e); } finally { _workingPaths.Remove(item.FilePath); } } }
private void EncodeThread() { for (;;) { Thread.Sleep(1000 * 1); if (this.State == ManagerState.Stop) return; BackgroundUploadItem item = null; try { lock (_thisLock) { if (_settings.UploadItems.Count > 0) { item = _settings.UploadItems .Where(n => n.State == BackgroundUploadState.Encoding) .FirstOrDefault(); } } } catch (Exception) { return; } if (item == null) continue; try { if (item.Groups.Count == 0 && item.Keys.Count == 0) { Stream stream = null; try { if (item.Scheme == "Broadcast") { if (item.Type == "Link") { var value = item.Link; if (value == null) throw new FormatException(); stream = ContentConverter.ToStream(value); } else if (item.Type == "Profile") { var value = item.Profile; if (value == null) throw new FormatException(); stream = ContentConverter.ToStream(value); } else if (item.Type == "Store") { var value = item.Store; if (value == null) throw new FormatException(); stream = ContentConverter.ToStream(value); } } else if (item.Scheme == "Unicast") { if (item.Type == "Message") { var value = item.Message; if (value == null) throw new FormatException(); stream = ContentConverter.ToCryptoStream(value, item.ExchangePublicKey); } } else if (item.Scheme == "Multicast") { if (item.Type == "Message") { var value = item.Message; if (value == null) throw new FormatException(); stream = ContentConverter.ToStream(value); } } else { throw new FormatException(); } if (stream.Length == 0) { lock (_thisLock) { if (item.Scheme == "Broadcast") { _connectionsManager.Upload(new BroadcastMetadata(item.Type, item.CreationTime, null, item.DigitalSignature)); } else if (item.Scheme == "Unicast") { _connectionsManager.Upload(new UnicastMetadata(item.Type, item.Signature, item.CreationTime, null, item.DigitalSignature)); } else if (item.Scheme == "Multicast") { _connectionsManager.Upload(new MulticastMetadata(item.Type, item.Tag, item.CreationTime, null, null, item.DigitalSignature)); } item.State = BackgroundUploadState.Completed; } } else { KeyCollection keys = null; try { using (ProgressStream encodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) => { isStop = (this.State == ManagerState.Stop || !_settings.UploadItems.Contains(item)); }, 1024 * 1024, true)) { if (stream.Length == 0) throw new InvalidOperationException("Stream Length"); encodingProgressStream.Seek(0, SeekOrigin.Begin); item.State = BackgroundUploadState.Encoding; keys = _cacheManager.Encoding(encodingProgressStream, CompressionAlgorithm.None, CryptoAlgorithm.None, null, item.BlockLength, item.HashAlgorithm); } } catch (StopIoException) { continue; } lock (_thisLock) { if (!_settings.UploadItems.Contains(item)) { foreach (var key in keys) { _cacheManager.Unlock(key); } continue; } foreach (var key in keys) { item.UploadKeys.Add(key); item.LockedKeys.Add(key); } item.Keys.AddRange(keys); } } } finally { if (stream != null) stream.Dispose(); } } else if (item.Groups.Count == 0 && item.Keys.Count == 1) { BroadcastMetadata broadcastMetadata = null; UnicastMetadata unicastMetadata = null; MulticastMetadata multicastMetadata = null; { var metadata = new Metadata(item.Depth, item.Keys[0], CompressionAlgorithm.None, CryptoAlgorithm.None, null); if (item.Scheme == "Broadcast") { broadcastMetadata = new BroadcastMetadata(item.Type, item.CreationTime, metadata, item.DigitalSignature); } else if (item.Scheme == "Unicast") { unicastMetadata = new UnicastMetadata(item.Type, item.Signature, item.CreationTime, metadata, item.DigitalSignature); } else if (item.Scheme == "Multicast") { var miner = new Miner(CashAlgorithm.Version1, item.MiningLimit, item.MiningTime); try { var task = Task.Run(() => { return new MulticastMetadata(item.Type, item.Tag, item.CreationTime, metadata, miner, item.DigitalSignature); }); while (!task.IsCompleted) { if (this.State == ManagerState.Stop) miner.Cancel(); lock (_thisLock) { if (!_settings.UploadItems.Contains(item)) { miner.Cancel(); } } Thread.Sleep(1000); } multicastMetadata = task.Result; } catch (Exception) { continue; } } } lock (_thisLock) { if (!_settings.UploadItems.Contains(item)) continue; if (item.Scheme == "Broadcast") { _connectionsManager.Upload(broadcastMetadata); } else if (item.Scheme == "Unicast") { _connectionsManager.Upload(unicastMetadata); } else if (item.Scheme == "Multicast") { _connectionsManager.Upload(multicastMetadata); } item.Keys.Clear(); foreach (var key in item.UploadKeys) { _connectionsManager.Upload(key); } item.State = BackgroundUploadState.Uploading; this.CheckState(item); } } else if (item.Keys.Count > 0) { var length = Math.Min(item.Keys.Count, 128); var keys = new KeyCollection(item.Keys.Take(length)); Group group = null; try { using (var tokenSource = new CancellationTokenSource()) { var task = _cacheManager.ParityEncoding(keys, item.HashAlgorithm, item.BlockLength, item.CorrectionAlgorithm, tokenSource.Token); while (!task.IsCompleted) { if (this.State == ManagerState.Stop || !_settings.UploadItems.Contains(item)) tokenSource.Cancel(); Thread.Sleep(1000); } group = task.Result; } } catch (Exception) { continue; } lock (_thisLock) { if (!_settings.UploadItems.Contains(item)) { foreach (var key in group.Keys.Skip(group.InformationLength)) { _cacheManager.Unlock(key); } continue; } foreach (var key in group.Keys.Skip(group.InformationLength)) { item.UploadKeys.Add(key); item.LockedKeys.Add(key); } item.Groups.Add(group); item.Keys.RemoveRange(0, length); } } else if (item.Groups.Count > 0 && item.Keys.Count == 0) { var index = new Index(); index.Groups.AddRange(item.Groups); KeyCollection keys = null; try { using (var stream = index.Export(_bufferManager)) using (ProgressStream encodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) => { isStop = (this.State == ManagerState.Stop || !_settings.UploadItems.Contains(item)); }, 1024 * 1024, true)) { encodingProgressStream.Seek(0, SeekOrigin.Begin); item.State = BackgroundUploadState.Encoding; keys = _cacheManager.Encoding(encodingProgressStream, CompressionAlgorithm.None, CryptoAlgorithm.None, null, item.BlockLength, item.HashAlgorithm); } } catch (StopIoException) { continue; } lock (_thisLock) { if (!_settings.UploadItems.Contains(item)) { foreach (var key in keys) { _cacheManager.Unlock(key); } continue; } foreach (var key in keys) { item.UploadKeys.Add(key); item.LockedKeys.Add(key); } item.Keys.AddRange(keys); item.Depth++; item.Groups.Clear(); } } } catch (Exception e) { item.State = BackgroundUploadState.Error; Log.Error(e); this.Remove(item); } } }
private void UploadManagerThread() { for (; ; ) { Thread.Sleep(1000 * 1); if (this.State == ManagerState.Stop) return; BackgroundUploadItem item = null; try { lock (this.ThisLock) { if (_settings.BackgroundUploadItems.Count > 0) { item = _settings.BackgroundUploadItems .Where(n => n.State == BackgroundUploadState.Encoding) .FirstOrDefault(); } } } catch (Exception) { return; } if (item == null) continue; try { if (item.Groups.Count == 0 && item.Keys.Count == 0) { Stream stream = null; try { if (item.Type == BackgroundItemType.Link) { var link = item.Value as Link; if (link == null) throw new FormatException(); stream = link.Export(_bufferManager); } else if (item.Type == BackgroundItemType.Store) { var store = item.Value as Store; if (store == null) throw new FormatException(); stream = store.Export(_bufferManager); } else { throw new FormatException(); } if (stream.Length == 0) { lock (this.ThisLock) { item.Seed.Rank = 0; if (item.DigitalSignature != null) { item.Seed.CreateCertificate(item.DigitalSignature); } _connectionsManager.Upload(item.Seed); item.State = BackgroundUploadState.Completed; } } else { KeyCollection keys = null; byte[] cryptoKey = null; try { using (ProgressStream encodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) => { isStop = (this.State == ManagerState.Stop || !_settings.BackgroundUploadItems.Contains(item)); }, 1024 * 1024, true)) { item.Seed.Length = stream.Length; if (item.Seed.Length == 0) throw new InvalidOperationException("Stream Length"); if (item.HashAlgorithm == HashAlgorithm.Sha256) { cryptoKey = Sha256.ComputeHash(encodingProgressStream); } encodingProgressStream.Seek(0, SeekOrigin.Begin); item.State = BackgroundUploadState.Encoding; keys = _cacheManager.Encoding(encodingProgressStream, item.CompressionAlgorithm, item.CryptoAlgorithm, cryptoKey, item.BlockLength, item.HashAlgorithm); } } catch (StopIoException) { continue; } lock (this.ThisLock) { foreach (var key in keys) { item.UploadKeys.Add(key); item.LockedKeys.Add(key); } item.CryptoKey = cryptoKey; item.Keys.AddRange(keys); } } } finally { if (stream != null) stream.Dispose(); } } else if (item.Groups.Count == 0 && item.Keys.Count == 1) { lock (this.ThisLock) { item.Seed.Rank = item.Rank; item.Seed.Key = item.Keys[0]; item.Keys.Clear(); item.Seed.CompressionAlgorithm = item.CompressionAlgorithm; item.Seed.CryptoAlgorithm = item.CryptoAlgorithm; item.Seed.CryptoKey = item.CryptoKey; if (item.DigitalSignature != null) { item.Seed.CreateCertificate(item.DigitalSignature); } item.UploadKeys.Add(item.Seed.Key); foreach (var key in item.UploadKeys) { _connectionsManager.Upload(key); } this.SetKeyCount(item); foreach (var key in item.LockedKeys) { _cacheManager.Unlock(key); } item.LockedKeys.Clear(); item.State = BackgroundUploadState.Uploading; _connectionsManager.Upload(item.Seed); } } else if (item.Keys.Count > 0) { var length = Math.Min(item.Keys.Count, 128); var keys = new KeyCollection(item.Keys.Take(length)); Group group = null; try { group = _cacheManager.ParityEncoding(keys, item.HashAlgorithm, item.BlockLength, item.CorrectionAlgorithm, (object state2) => { return (this.State == ManagerState.Stop || !_settings.BackgroundUploadItems.Contains(item)); }); } catch (StopException) { continue; } lock (this.ThisLock) { foreach (var key in group.Keys.Skip(group.InformationLength)) { item.UploadKeys.Add(key); item.LockedKeys.Add(key); } item.Groups.Add(group); item.Keys.RemoveRange(0, length); } } else if (item.Groups.Count > 0 && item.Keys.Count == 0) { var index = new Index(); index.Groups.AddRange(item.Groups); index.CompressionAlgorithm = item.CompressionAlgorithm; index.CryptoAlgorithm = item.CryptoAlgorithm; index.CryptoKey = item.CryptoKey; byte[] cryptoKey = null; KeyCollection keys = null; try { using (var stream = index.Export(_bufferManager)) using (ProgressStream encodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) => { isStop = (this.State == ManagerState.Stop || !_settings.BackgroundUploadItems.Contains(item)); }, 1024 * 1024, true)) { if (item.HashAlgorithm == HashAlgorithm.Sha256) { cryptoKey = Sha256.ComputeHash(encodingProgressStream); } encodingProgressStream.Seek(0, SeekOrigin.Begin); item.State = BackgroundUploadState.Encoding; keys = _cacheManager.Encoding(encodingProgressStream, item.CompressionAlgorithm, item.CryptoAlgorithm, cryptoKey, item.BlockLength, item.HashAlgorithm); } } catch (StopIoException) { continue; } lock (this.ThisLock) { foreach (var key in keys) { item.UploadKeys.Add(key); item.LockedKeys.Add(key); } item.CryptoKey = cryptoKey; item.Keys.AddRange(keys); item.Rank++; item.Groups.Clear(); } } } catch (Exception e) { item.State = BackgroundUploadState.Error; Log.Error(e); this.Remove(item); } } }
private void DecodeManagerThread() { for (; ; ) { Thread.Sleep(1000 * 3); if (this.State == ManagerState.Stop) return; BackgroundDownloadItem item = null; try { lock (this.ThisLock) { if (_settings.BackgroundDownloadItems.Count > 0) { item = _settings.BackgroundDownloadItems .Where(n => n.State == BackgroundDownloadState.Decoding) .OrderBy(n => (n.Rank != n.Seed.Rank) ? 0 : 1) .FirstOrDefault(); } } } catch (Exception) { return; } if (item == null) continue; try { if (item.Rank == 1) { if (!_cacheManager.Contains(item.Seed.Key)) { item.State = BackgroundDownloadState.Downloading; } else { item.State = BackgroundDownloadState.Decoding; if (item.Rank < item.Seed.Rank) { string fileName = null; bool largeFlag = false; try { using (FileStream stream = BackgroundDownloadManager.GetUniqueFileStream(Path.Combine(_workDirectory, "index"))) using (ProgressStream decodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) => { isStop = (this.State == ManagerState.Stop || !_settings.BackgroundDownloadItems.Contains(item)); if (!isStop && (stream.Length > item.Seed.Length)) { isStop = true; largeFlag = true; } }, 1024 * 1024, true)) { fileName = stream.Name; _cacheManager.Decoding(decodingProgressStream, item.Seed.CompressionAlgorithm, item.Seed.CryptoAlgorithm, item.Seed.CryptoKey, new KeyCollection() { item.Seed.Key }); } } catch (StopIoException) { if (File.Exists(fileName)) File.Delete(fileName); if (largeFlag) { throw new Exception(); } continue; } catch (Exception) { if (File.Exists(fileName)) File.Delete(fileName); throw; } Index index; using (FileStream stream = new FileStream(fileName, FileMode.Open)) { index = Index.Import(stream, _bufferManager); } File.Delete(fileName); lock (this.ThisLock) { this.UncheckState(item.Index); item.Index = index; this.CheckState(item.Index); foreach (var group in item.Index.Groups) { foreach (var key in group.Keys) { _cacheManager.Lock(key); } } item.Indexes.Add(index); item.Rank++; item.State = BackgroundDownloadState.Downloading; } } else { bool largeFlag = false; object value = null; try { using (Stream stream = new BufferStream(_bufferManager)) using (ProgressStream decodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) => { isStop = (this.State == ManagerState.Stop || !_settings.BackgroundDownloadItems.Contains(item)); if (!isStop && (stream.Length > item.Seed.Length)) { isStop = true; largeFlag = true; } }, 1024 * 1024, true)) { _cacheManager.Decoding(decodingProgressStream, item.Seed.CompressionAlgorithm, item.Seed.CryptoAlgorithm, item.Seed.CryptoKey, new KeyCollection() { item.Seed.Key }); if (stream.Length != item.Seed.Length) throw new Exception(); stream.Seek(0, SeekOrigin.Begin); if (item.Type == BackgroundItemType.Link) { value = Link.Import(stream, _bufferManager); } else if (item.Type == BackgroundItemType.Store) { value = Store.Import(stream, _bufferManager); } } } catch (StopIoException) { if (largeFlag) { throw new Exception(); } continue; } catch (Exception) { throw; } lock (this.ThisLock) { item.Value = value; if (item.Seed.Key != null) { _cacheManager.Unlock(item.Seed.Key); } foreach (var index in item.Indexes) { foreach (var group in index.Groups) { foreach (var key in group.Keys) { _cacheManager.Unlock(key); } } } item.Indexes.Clear(); item.State = BackgroundDownloadState.Completed; } } } } else { if (!item.Index.Groups.All(n => _existManager.GetCount(n) >= n.InformationLength)) { item.State = BackgroundDownloadState.Downloading; } else { List<Key> keys = new List<Key>(); try { foreach (var group in item.Index.Groups.ToArray()) { keys.AddRange(_cacheManager.ParityDecoding(group, (object state2) => { return (this.State == ManagerState.Stop || !_settings.BackgroundDownloadItems.Contains(item)); })); } } catch (StopException) { continue; } item.State = BackgroundDownloadState.Decoding; if (item.Rank < item.Seed.Rank) { string fileName = null; bool largeFlag = false; try { using (FileStream stream = BackgroundDownloadManager.GetUniqueFileStream(Path.Combine(_workDirectory, "index"))) using (ProgressStream decodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) => { isStop = (this.State == ManagerState.Stop || !_settings.BackgroundDownloadItems.Contains(item)); if (!isStop && (stream.Length > item.Seed.Length)) { isStop = true; largeFlag = true; } }, 1024 * 1024, true)) { fileName = stream.Name; _cacheManager.Decoding(decodingProgressStream, item.Index.CompressionAlgorithm, item.Index.CryptoAlgorithm, item.Index.CryptoKey, new KeyCollection(keys)); } } catch (StopIoException) { if (File.Exists(fileName)) File.Delete(fileName); if (largeFlag) { throw new Exception(); } continue; } catch (Exception) { if (File.Exists(fileName)) File.Delete(fileName); throw; } Index index; using (FileStream stream = new FileStream(fileName, FileMode.Open)) { index = Index.Import(stream, _bufferManager); } File.Delete(fileName); lock (this.ThisLock) { this.UncheckState(item.Index); item.Index = index; this.CheckState(item.Index); foreach (var group in item.Index.Groups) { foreach (var key in group.Keys) { _cacheManager.Lock(key); } } item.Indexes.Add(index); item.Rank++; item.State = BackgroundDownloadState.Downloading; } } else { item.State = BackgroundDownloadState.Decoding; bool largeFlag = false; object value = null; try { using (Stream stream = new BufferStream(_bufferManager)) using (ProgressStream decodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) => { isStop = (this.State == ManagerState.Stop || !_settings.BackgroundDownloadItems.Contains(item)); if (!isStop && (stream.Length > item.Seed.Length)) { isStop = true; largeFlag = true; } }, 1024 * 1024, true)) { _cacheManager.Decoding(decodingProgressStream, item.Index.CompressionAlgorithm, item.Index.CryptoAlgorithm, item.Index.CryptoKey, new KeyCollection(keys)); if (stream.Length != item.Seed.Length) throw new Exception(); stream.Seek(0, SeekOrigin.Begin); if (item.Type == BackgroundItemType.Link) { value = Link.Import(stream, _bufferManager); } else if (item.Type == BackgroundItemType.Store) { value = Store.Import(stream, _bufferManager); } } } catch (StopIoException) { if (largeFlag) { throw new Exception(); } continue; } catch (Exception) { throw; } lock (this.ThisLock) { item.Value = value; if (item.Seed.Key != null) { _cacheManager.Unlock(item.Seed.Key); } foreach (var index in item.Indexes) { foreach (var group in index.Groups) { foreach (var key in group.Keys) { _cacheManager.Unlock(key); } } } item.Indexes.Clear(); item.State = BackgroundDownloadState.Completed; } } } } } catch (Exception e) { if (_cacheManager.Contains(item.Seed.Key)) { ArraySegment<byte> buffer = new ArraySegment<byte>(); try { buffer = _cacheManager[item.Seed.Key]; } catch (Exception) { } finally { if (buffer.Array != null) { _bufferManager.ReturnBuffer(buffer.Array); } } } foreach (var index in item.Indexes) { foreach (var group in index.Groups) { foreach (var key in group.Keys) { if (this.State == ManagerState.Stop) return; if (!_cacheManager.Contains(key)) continue; ArraySegment<byte> buffer = new ArraySegment<byte>(); try { buffer = _cacheManager[key]; } catch (Exception) { } finally { if (buffer.Array != null) { _bufferManager.ReturnBuffer(buffer.Array); } } } } } item.State = BackgroundDownloadState.Error; Log.Error(e); } } }
private void DecodeThread() { var random = new Random(); for (;;) { Thread.Sleep(1000 * 3); if (this.DecodeState == ManagerState.Stop) return; DownloadItem item = null; try { lock (_thisLock) { if (_settings.DownloadItems.Count > 0) { item = _settings.DownloadItems .Where(n => !_workingSeeds.Contains(n.Seed)) .Where(n => n.State == DownloadState.Decoding || n.State == DownloadState.ParityDecoding) .Where(n => n.Priority != 0) .OrderBy(n => (n.Depth != n.Seed.Metadata.Depth) ? 0 : 1) .OrderBy(n => (n.State == DownloadState.Decoding) ? 0 : 1) .FirstOrDefault(); if (item != null) { _workingSeeds.Add(item.Seed); } } } } catch (Exception) { return; } if (item == null) continue; try { { if ((item.Depth == 1 && !_cacheManager.Contains(item.Seed.Metadata.Key)) || (item.Depth > 1 && !item.Index.Groups.All(n => _existManager.GetCount(n) >= n.InformationLength))) { item.State = DownloadState.Downloading; } else { var keys = new KeyCollection(); var compressionAlgorithm = CompressionAlgorithm.None; var cryptoAlgorithm = CryptoAlgorithm.None; byte[] cryptoKey = null; if (item.Depth == 1) { keys.Add(item.Seed.Metadata.Key); compressionAlgorithm = item.Seed.Metadata.CompressionAlgorithm; cryptoAlgorithm = item.Seed.Metadata.CryptoAlgorithm; cryptoKey = item.Seed.Metadata.CryptoKey; } else { item.State = DownloadState.ParityDecoding; item.DecodeOffset = 0; item.DecodeLength = item.Index.Groups.Sum(n => n.Length); try { foreach (var group in item.Index.Groups.ToArray()) { using (var tokenSource = new CancellationTokenSource()) { var task = _cacheManager.ParityDecoding(group, tokenSource.Token); while (!task.IsCompleted) { if (this.DecodeState == ManagerState.Stop || !_settings.DownloadItems.Contains(item)) tokenSource.Cancel(); Thread.Sleep(1000); } keys.AddRange(task.Result); } item.DecodeOffset += group.Length; } } catch (Exception) { continue; } compressionAlgorithm = item.Index.CompressionAlgorithm; cryptoAlgorithm = item.Index.CryptoAlgorithm; cryptoKey = item.Index.CryptoKey; } item.State = DownloadState.Decoding; if (item.Depth < item.Seed.Metadata.Depth) { string fileName = null; bool largeFlag = false; try { item.DecodeOffset = 0; item.DecodeLength = keys.Sum(n => (long)_cacheManager.GetLength(n)); using (var stream = DownloadManager.GetUniqueFileStream(Path.Combine(_workDirectory, "index"))) using (ProgressStream decodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) => { isStop = (this.DecodeState == ManagerState.Stop || !_settings.DownloadItems.Contains(item)); if (!isStop && (stream.Length > item.Seed.Length)) { isStop = true; largeFlag = true; } item.DecodeOffset = writeSize; }, 1024 * 1024, true)) { fileName = stream.Name; _cacheManager.Decoding(decodingProgressStream, compressionAlgorithm, cryptoAlgorithm, cryptoKey, keys); } } catch (StopIoException) { if (File.Exists(fileName)) { File.Delete(fileName); } if (largeFlag) { throw new Exception("size too large."); } continue; } catch (Exception) { if (File.Exists(fileName)) { File.Delete(fileName); } throw; } Index index; using (var stream = new UnbufferedFileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, FileOptions.None, _bufferManager)) { index = Index.Import(stream, _bufferManager); } File.Delete(fileName); lock (_thisLock) { if (!_settings.DownloadItems.Contains(item)) continue; item.DecodeOffset = 0; item.DecodeLength = 0; this.UncheckState(item.Index); item.Index = index; this.CheckState(item.Index); foreach (var group in item.Index.Groups) { foreach (var key in group.Keys) { _cacheManager.Lock(key); } } item.Indexes.Add(index); item.Depth++; item.State = DownloadState.Downloading; } } else { item.State = DownloadState.Decoding; string fileName = null; bool largeFlag = false; string downloadDirectory; if (item.Path == null) { downloadDirectory = this.BaseDirectory; } else { if (Path.IsPathRooted(item.Path)) { downloadDirectory = item.Path; } else { downloadDirectory = Path.Combine(this.BaseDirectory, item.Path); } } Directory.CreateDirectory(downloadDirectory); try { item.DecodeOffset = 0; item.DecodeLength = keys.Sum(n => (long)_cacheManager.GetLength(n)); using (var stream = DownloadManager.GetUniqueFileStream(Path.Combine(downloadDirectory, string.Format("{0}.tmp", DownloadManager.GetNormalizedPath(item.Seed.Name))))) using (ProgressStream decodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) => { isStop = (this.DecodeState == ManagerState.Stop || !_settings.DownloadItems.Contains(item)); if (!isStop && (stream.Length > item.Seed.Length)) { isStop = true; largeFlag = true; } item.DecodeOffset = writeSize; }, 1024 * 1024, true)) { fileName = stream.Name; _cacheManager.Decoding(decodingProgressStream, compressionAlgorithm, cryptoAlgorithm, cryptoKey, keys); if (stream.Length != item.Seed.Length) throw new Exception("Stream.Length != Seed.Length"); } } catch (StopIoException) { if (File.Exists(fileName)) { File.Delete(fileName); } if (largeFlag) { throw new Exception("size too large."); } continue; } catch (Exception) { if (File.Exists(fileName)) { File.Delete(fileName); } throw; } File.Move(fileName, DownloadManager.GetUniqueFilePath(Path.Combine(downloadDirectory, DownloadManager.GetNormalizedPath(item.Seed.Name)))); lock (_thisLock) { if (!_settings.DownloadItems.Contains(item)) continue; item.DecodeOffset = 0; item.DecodeLength = 0; { var usingKeys = new HashSet<Key>(); foreach (var index in item.Indexes) { foreach (var group in index.Groups) { usingKeys.UnionWith(group.Keys .Where(n => _cacheManager.Contains(n)) .Reverse() .Take(group.InformationLength)); } } _cacheManager.SetSeed(item.Seed.Clone(), usingKeys.ToArray()); } _settings.DownloadedSeeds.Add(item.Seed.Clone()); _cacheManager.Unlock(item.Seed.Metadata.Key); foreach (var index in item.Indexes) { foreach (var group in index.Groups) { foreach (var key in group.Keys) { _cacheManager.Unlock(key); } } } item.Indexes.Clear(); item.State = DownloadState.Completed; } } } } } catch (Exception e) { // Check { var list = new List<Key>(); list.Add(item.Seed.Metadata.Key); foreach (var index in item.Indexes) { foreach (var group in index.Groups) { foreach (var key in group.Keys) { list.Add(key); } } } foreach (var key in list) { if (this.DecodeState == ManagerState.Stop) return; if (!_cacheManager.Contains(key)) continue; var buffer = new ArraySegment<byte>(); try { buffer = _cacheManager[key]; } catch (Exception) { } finally { if (buffer.Array != null) { _bufferManager.ReturnBuffer(buffer.Array); } } } } item.State = DownloadState.Error; Log.Error(e); } finally { _workingSeeds.Remove(item.Seed); } } }