private void Remove(BackgroundDownloadItem item) { lock (this.ThisLock) { if (item.State != BackgroundDownloadState.Completed) { 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); } } } } this.UncheckState(item.Index); _settings.BackgroundDownloadItems.Remove(item); } }
private void Download(Seed seed, BackgroundItemType type, object value) { if (seed == null) return; lock (this.ThisLock) { if (_settings.BackgroundDownloadItems.Any(n => n.Seed == seed)) return; if (seed.Rank == 0) { BackgroundDownloadItem item = new BackgroundDownloadItem(); item.Rank = 0; item.Seed = seed; item.State = BackgroundDownloadState.Completed; item.Type = type; if (item.Type == BackgroundItemType.Link) { item.Value = new Link(); } else if (item.Type == BackgroundItemType.Store) { item.Value = new Store(); } else { throw new FormatException(); } _settings.BackgroundDownloadItems.Add(item); } else { if (seed.Key == null) return; BackgroundDownloadItem item = new BackgroundDownloadItem(); item.Rank = 1; item.Seed = seed; item.State = BackgroundDownloadState.Downloading; item.Type = type; item.Value = value; if (item.Seed.Key != null) { _cacheManager.Lock(item.Seed.Key); } _settings.BackgroundDownloadItems.Add(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 DownloadManagerThread() { Random random = new Random(); int round = 0; for (; ;) { Thread.Sleep(1000 * 3); if (this.State == ManagerState.Stop) { return; } BackgroundDownloadItem item = null; try { lock (this.ThisLock) { if (_settings.BackgroundDownloadItems.Count > 0) { { var items = _settings.BackgroundDownloadItems .Where(n => n.State == BackgroundDownloadState.Downloading) .Where(x => { if (x.Rank == 1) { return(0 == (!_cacheManager.Contains(x.Seed.Key) ? 1 : 0)); } else { return(0 == (x.Index.Groups.Sum(n => n.InformationLength) - x.Index.Groups.Sum(n => Math.Min(n.InformationLength, _existManager.GetCount(n))))); } }) .ToList(); item = items.FirstOrDefault(); } if (item == null) { var items = _settings.BackgroundDownloadItems .Where(n => n.State == BackgroundDownloadState.Downloading) .ToList(); if (items.Count > 0) { round = (round >= items.Count) ? 0 : round; item = items[round++]; } } } } } catch (Exception) { return; } if (item == null) { continue; } try { if (item.Rank == 1) { if (!_cacheManager.Contains(item.Seed.Key)) { item.State = BackgroundDownloadState.Downloading; _connectionsManager.Download(item.Seed.Key); } else { item.State = BackgroundDownloadState.Decoding; } } else { if (!item.Index.Groups.All(n => _existManager.GetCount(n) >= n.InformationLength)) { item.State = BackgroundDownloadState.Downloading; int limitCount = 256; foreach (var group in item.Index.Groups.ToArray().Randomize()) { if (_existManager.GetCount(group) >= group.InformationLength) { continue; } foreach (var key in _existManager.GetKeys(group, false)) { if (_connectionsManager.IsDownloadWaiting(key)) { limitCount--; if (limitCount <= 0) { goto End; } } } } List <Key> keyList = new List <Key>(); foreach (var group in item.Index.Groups.ToArray()) { if (_existManager.GetCount(group) >= group.InformationLength) { continue; } int downloadCount = 0; List <Key> tempKeys = new List <Key>(); foreach (var key in _existManager.GetKeys(group, false)) { if (_connectionsManager.IsDownloadWaiting(key)) { downloadCount++; } else { tempKeys.Add(key); } } int length = Math.Max(group.InformationLength, 32) - downloadCount; if (length <= 0) { continue; } random.Shuffle(tempKeys); foreach (var key in tempKeys.Take(length)) { _connectionsManager.Download(key); limitCount--; } if (limitCount <= 0) { goto End; } } End :; } else { item.State = BackgroundDownloadState.Decoding; } } } catch (Exception e) { item.State = BackgroundDownloadState.Error; Log.Error(e); this.Remove(item); } } }
private void Download(Seed seed, BackgroundItemType type, object value) { if (seed == null) { return; } lock (this.ThisLock) { if (_settings.BackgroundDownloadItems.Any(n => n.Seed == seed)) { return; } if (seed.Rank == 0) { BackgroundDownloadItem item = new BackgroundDownloadItem(); item.Rank = 0; item.Seed = seed; item.State = BackgroundDownloadState.Completed; item.Type = type; if (item.Type == BackgroundItemType.Link) { item.Value = new Link(); } else if (item.Type == BackgroundItemType.Store) { item.Value = new Store(); } else { throw new FormatException(); } _settings.BackgroundDownloadItems.Add(item); } else { if (seed.Key == null) { return; } BackgroundDownloadItem item = new BackgroundDownloadItem(); item.Rank = 1; item.Seed = seed; item.State = BackgroundDownloadState.Downloading; item.Type = type; item.Value = value; if (item.Seed.Key != null) { _cacheManager.Lock(item.Seed.Key); } _settings.BackgroundDownloadItems.Add(item); } } }