<commit_before>﻿using System;
using System.Collections.Generic;
using Hadouken.Common.BitTorrent;
using Hadouken.Common.Messaging;
using Ragnar;

namespace Hadouken.Core.BitTorrent
{
    internal class TorrentManager : ITorrentManager
    {
        private readonly IAlertBus _alertBus;
        private readonly IMessageBus _messageBus;
        private readonly ITorrentInfoRepository _torrentInfoRepository;
        private readonly IDictionary<string, Torrent> _torrents;  

        public TorrentManager(IAlertBus alertBus, IMessageBus messageBus, ITorrentInfoRepository torrentInfoRepository)
        {
            if (alertBus == null) throw new ArgumentNullException("alertBus");
            if (messageBus == null) throw new ArgumentNullException("messageBus");
            if (torrentInfoRepository == null) throw new ArgumentNullException("torrentInfoRepository");

            _alertBus = alertBus;
            _messageBus = messageBus;
            _torrentInfoRepository = torrentInfoRepository;
            _torrents = new Dictionary<string, Torrent>(StringComparer.OrdinalIgnoreCase);
        }

        public IDictionary<string, Torrent> Torrents
        {
            get { return _torrents; }
        }

        public void Load()
        {
            // Set up alert subscriptions
            _alertBus.Subscribe<MetadataReceivedAlert>(OnMetadataReceived);
            _alertBus.Subscribe<StateUpdateAlert>(OnStateUpdate);
            _alertBus.Subscribe<TorrentAddedAlert>(OnTorrentAdded);
            _alertBus.Subscribe<TorrentFinishedAlert>(OnTorrentFinished);
            _alertBus.Subscribe<TorrentRemovedAlert>(OnTorrentRemoved);
        }

        public void Unload()
        {
        }

        private void OnMetadataReceived(MetadataReceivedAlert alert)
        {
            using (var handle = alert.Handle)
            {
                Torrent torrent;
                if (!_torrents.TryGetValue(handle.InfoHash.ToHex(), out torrent)) return;

                torrent.TorrentInfo = handle.TorrentFile;
                _torrentInfoRepository.Save(torrent.TorrentInfo);
            }
        }

        private void OnTorrentAdded(TorrentAddedAlert alert)
        {
            var torrent = new Torrent(alert.Handle);
            _torrents.Add(torrent.InfoHash, torrent);

            _messageBus.Publish(new TorrentAddedMessage(torrent));
        }

        private void OnTorrentFinished(TorrentFinishedAlert alert)
        {
            using (var handle = alert.Handle)
            {
                Torrent torrent;
                if (!_torrents.TryGetValue(handle.InfoHash.ToHex(), out torrent)) return;

                // Update status
                torrent.Status = handle.QueryStatus();

                // If the total downloaded bytes are 0 we probably just added a torrent
                // which was already downloaded. 
                if (torrent.TotalDownloadedBytes == 0)
                {
                    return;
                }

                _messageBus.Publish(new TorrentCompletedMessage(torrent));
            }
        }

        private void OnTorrentRemoved(TorrentRemovedAlert alert)
        {
            var torrent = _torrents[alert.InfoHash];
            torrent.Dispose();

            _torrents.Remove(alert.InfoHash);

            _messageBus.Publish(new TorrentRemovedMessage(alert.InfoHash));
        }

        private void OnStateUpdate(StateUpdateAlert alert)
        {
            foreach (var status in alert.Statuses)
            {
                var torrent = _torrents[status.InfoHash.ToHex()];
                if (torrent == null) continue;

                torrent.Status = status;
            }
        }
    }
}<commit_msg>Switched to a concurrent dictionary.<commit_after>﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Hadouken.Common.BitTorrent;
using Hadouken.Common.Messaging;
using Ragnar;

namespace Hadouken.Core.BitTorrent
{
    internal class TorrentManager : ITorrentManager
    {
        private readonly IAlertBus _alertBus;
        private readonly IMessageBus _messageBus;
        private readonly ITorrentInfoRepository _torrentInfoRepository;
        private readonly ConcurrentDictionary<string, Torrent> _torrents;  

        public TorrentManager(IAlertBus alertBus, IMessageBus messageBus, ITorrentInfoRepository torrentInfoRepository)
        {
            if (alertBus == null) throw new ArgumentNullException("alertBus");
            if (messageBus == null) throw new ArgumentNullException("messageBus");
            if (torrentInfoRepository == null) throw new ArgumentNullException("torrentInfoRepository");

            _alertBus = alertBus;
            _messageBus = messageBus;
            _torrentInfoRepository = torrentInfoRepository;
            _torrents = new ConcurrentDictionary<string, Torrent>(StringComparer.OrdinalIgnoreCase);
        }

        public IDictionary<string, Torrent> Torrents
        {
            get { return _torrents; }
        }

        public void Load()
        {
            // Set up alert subscriptions
            _alertBus.Subscribe<MetadataReceivedAlert>(OnMetadataReceived);
            _alertBus.Subscribe<StateUpdateAlert>(OnStateUpdate);
            _alertBus.Subscribe<TorrentAddedAlert>(OnTorrentAdded);
            _alertBus.Subscribe<TorrentFinishedAlert>(OnTorrentFinished);
            _alertBus.Subscribe<TorrentRemovedAlert>(OnTorrentRemoved);
        }

        public void Unload()
        {
        }

        private void OnMetadataReceived(MetadataReceivedAlert alert)
        {
            using (var handle = alert.Handle)
            {
                Torrent torrent;
                if (!_torrents.TryGetValue(handle.InfoHash.ToHex(), out torrent)) return;

                torrent.TorrentInfo = handle.TorrentFile;
                _torrentInfoRepository.Save(torrent.TorrentInfo);
            }
        }

        private void OnTorrentAdded(TorrentAddedAlert alert)
        {
            var torrent = new Torrent(alert.Handle);
            
            if (_torrents.TryAdd(torrent.InfoHash, torrent))
            {
                _messageBus.Publish(new TorrentAddedMessage(torrent));   
            }
        }

        private void OnTorrentFinished(TorrentFinishedAlert alert)
        {
            using (var handle = alert.Handle)
            {
                Torrent torrent;
                if (!_torrents.TryGetValue(handle.InfoHash.ToHex(), out torrent)) return;

                // Update status
                torrent.Status = handle.QueryStatus();

                // If the total downloaded bytes are 0 we probably just added a torrent
                // which was already downloaded. 
                if (torrent.TotalDownloadedBytes == 0)
                {
                    return;
                }

                _messageBus.Publish(new TorrentCompletedMessage(torrent));
            }
        }

        private void OnTorrentRemoved(TorrentRemovedAlert alert)
        {
            Torrent torrent;

            if (_torrents.TryRemove(alert.InfoHash, out torrent))
            {
                torrent.Dispose();                
            }

            _messageBus.Publish(new TorrentRemovedMessage(alert.InfoHash));
        }

        private void OnStateUpdate(StateUpdateAlert alert)
        {
            foreach (var status in alert.Statuses)
            {
                Torrent torrent;
                if (!_torrents.TryGetValue(status.InfoHash.ToHex(), out torrent)) continue;

                torrent.Status = status;
            }
        }
    }
}
{'fraction_non_alphanumeric': 0.07353519465198584, 'fraction_numerical': 0.0005243151133831433, 'mean_word_length': 1.9769801014436208, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4147941', 'n_tokens_mistral': 1992, 'n_tokens_neox': 1870, 'n_words': 391}