void CDownloads::OnRun()
{
	DWORD nActiveDownloads		= 0;	// Number of downloads that are doing something
	DWORD nActiveTransfers		= 0;	// Number of transfers that are in the downloading state
	DWORD nTotalTransfers		= 0;	// Total transfers
	DWORD nTotalBandwidth		= 0;	// Total bandwidth in use
	DWORD nRunningTransfers		= 0;	// Number of transfers that are downloading and transfering data
	DWORD nRunningED2KTransfers	= 0;	// Number of ed2k transfers that are downloading and transfering data
	DWORD nTotalED2KBandwidth	= 0;	// Total ed2k bandwidth in use.

	{
		CTransfers::Lock oLock;

		m_nValidation = 0;
		++m_nRunCookie;
		
		for ( POSITION pos = GetIterator(); pos; )
		{
			CDownload* pDownload = GetNext( pos );
			pDownload->m_nRunCookie = m_nRunCookie;
			pDownload->OnRun();
			
			int nTemp = 0;
			
			for ( CDownloadTransfer* pTransfer = pDownload->GetFirstTransfer() ; pTransfer ; pTransfer = pTransfer->m_pDlNext )
			{
				if ( pTransfer->m_nProtocol == PROTOCOL_ED2K )
				{
					CDownloadTransferED2K* pED2K = (CDownloadTransferED2K*)pTransfer;
					if ( pED2K->m_pClient == NULL || pED2K->m_pClient->m_bConnected == FALSE ) continue;
					if ( pTransfer->m_nState == dtsQueued ) continue;
				}
				else if ( pTransfer->m_nProtocol == PROTOCOL_BT )
				{
					CDownloadTransferBT* pBT = (CDownloadTransferBT*)pTransfer;
					if ( pBT->m_nState == dtsTorrent && pBT->m_bChoked ) continue;
				}
				
				nTemp ++;
				
				if ( pTransfer->m_nState == dtsDownloading )
				{
					DWORD nSpeed = pTransfer->GetMeasuredSpeed();
					nTotalBandwidth += nSpeed;
					nActiveTransfers ++;
					if ( nSpeed > 32 ) nRunningTransfers ++; 

					if ( pTransfer->m_nProtocol == PROTOCOL_ED2K ) 
					{
						nTotalED2KBandwidth += nSpeed;
						if ( nSpeed > 32 ) nRunningED2KTransfers ++;
					}
				}
			}
			
			if ( nTemp )
			{
				nActiveDownloads ++;
				nTotalTransfers += nTemp;
			}
		}
	}

	m_nTransfers = nActiveTransfers;
	m_nBandwidth = nTotalBandwidth;
	
	m_bAllowMoreDownloads = nActiveDownloads < (DWORD)Settings.Downloads.MaxFiles;
	m_bAllowMoreTransfers = nTotalTransfers < (DWORD)Settings.Downloads.MaxTransfers;
	
	// Transfers that are not managing at least 32 bytes/sec are not counted when averaging limits
	if ( nRunningTransfers > 0 )
	{
		m_nLimitGeneric	= Settings.Bandwidth.Downloads / nRunningTransfers;
		m_nLimitDonkey = m_nLimitGeneric;
		if ( UploadQueues.IsDonkeyRatioActive() )
		{
			// Use either the minimum we have reserved, or the current upload allocation, whichever is greater.
			DWORD nDonkeyLimit = max( UploadQueues.GetMinimumDonkeyBandwidth(), UploadQueues.GetCurrentDonkeyBandwidth() );
		
			if ( nDonkeyLimit < 10240 )
			{
				// ED2K 3:1 ratio if you aren't uploading at 10KB/s
				nDonkeyLimit *= 3;	

				// Because this is a per-source limit, we should check overall usage as well.
				if ( nTotalED2KBandwidth > ( nDonkeyLimit / 2 ) )
				{
					// We're getting close to the ed2k ratio, so we need to limit some sources.

					if ( nRunningED2KTransfers > 0 )
						m_nLimitDonkey = nDonkeyLimit / nRunningED2KTransfers;
					else 
						m_nLimitDonkey = nDonkeyLimit;

				}

				// Make sure we have not set the ed2k limit higher than the general limit
				if ( m_nLimitGeneric ) m_nLimitDonkey = min( m_nLimitGeneric, m_nLimitDonkey );
			}
		}
	}
	else
	{
		m_nLimitGeneric = m_nLimitDonkey = Settings.Bandwidth.Downloads;
	}
	
	DownloadGroups.Save( FALSE );
}