File indexing completed on 2025-01-05 04:37:21
0001 /* 0002 SPDX-FileCopyrightText: 2012 Joris Guisson <joris.guisson@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "connectionlimit.h" 0008 #include <util/functions.h> 0009 0010 namespace bt 0011 { 0012 static bt::Uint32 SystemConnectionLimit() 0013 { 0014 #ifndef Q_WS_WIN 0015 return bt::MaxOpenFiles() - 50; // leave about 50 free for regular files 0016 #else 0017 return 9999; // there isn't a real limit on windows 0018 #endif 0019 } 0020 0021 ConnectionLimit::ConnectionLimit() 0022 : global_limit(SystemConnectionLimit()) 0023 , global_total(0) 0024 , torrent_limit(0) 0025 { 0026 } 0027 0028 ConnectionLimit::~ConnectionLimit() 0029 { 0030 } 0031 0032 void ConnectionLimit::setLimits(Uint32 global_limit, Uint32 torrent_limit) 0033 { 0034 this->global_limit = global_limit; 0035 this->torrent_limit = torrent_limit; 0036 if (this->global_limit > SystemConnectionLimit()) 0037 this->global_limit = SystemConnectionLimit(); 0038 } 0039 0040 ConnectionLimit::Token::Ptr ConnectionLimit::acquire(const SHA1Hash &hash) 0041 { 0042 if (global_limit != 0 && global_total >= global_limit) 0043 return Token::Ptr(); 0044 0045 QMap<SHA1Hash, bt::Uint32>::iterator i = torrent_totals.find(hash); 0046 if (i == torrent_totals.end()) { 0047 torrent_totals[hash] = 1; 0048 global_total++; 0049 return Token::Ptr(new Token(*this, hash)); 0050 } else if (torrent_limit == 0 || i.value() < torrent_limit) { 0051 i.value()++; 0052 global_total++; 0053 return Token::Ptr(new Token(*this, hash)); 0054 } 0055 0056 return Token::Ptr(); 0057 } 0058 0059 void ConnectionLimit::release(const ConnectionLimit::Token &token) 0060 { 0061 QMap<SHA1Hash, bt::Uint32>::iterator i = torrent_totals.find(token.infoHash()); 0062 if (i != torrent_totals.end()) { 0063 if (i.value() > 0) 0064 i.value()--; 0065 0066 // erase when torrent has no tokens left 0067 if (i.value() == 0) 0068 torrent_totals.erase(i); 0069 0070 if (global_total > 0) 0071 global_total--; 0072 } 0073 } 0074 0075 ConnectionLimit::Token::Token(ConnectionLimit &limit, const SHA1Hash &hash) 0076 : limit(limit) 0077 , hash(hash) 0078 { 0079 } 0080 0081 ConnectionLimit::Token::~Token() 0082 { 0083 limit.release(*this); 0084 } 0085 0086 }