618
624
// Requested_Block_Struct* toadd[count];
619
625
std::vector<Requested_Block_Struct*> toadd(count);
621
bool bIsAvailable = m_reqfile->GetNextRequestedBlock(this, &(toadd[0]), &count);
627
bool bIsAvailable = m_reqfile->GetNextRequestedBlock(this, toadd, count);
622
628
//dazzle: if no blocks available, try to drop the slowest source, then try again
623
629
if (!bIsAvailable) {
624
if (bSourceHasBeenDropped = m_reqfile->DropSlowestSource(this)) {
630
bSourceHasBeenDropped = m_reqfile->DropSlowestSource(this);
631
if (bSourceHasBeenDropped) {
625
632
// riporto count al valore iniziale e ri-provo
626
633
count = countinit;
627
bIsAvailable = m_reqfile->GetNextRequestedBlock(this, &(toadd[0]), &count);
634
bIsAvailable = m_reqfile->GetNextRequestedBlock(this, toadd, count);
707
714
// rilascio della fonte NON con download rate sotto la media (come l'originale)
708
715
// ma con rate inferiore a tutti gli altri
710
718
if (m_DownloadBlocks_list.empty()) {
711
719
// Barry - instead of getting 3, just get how many is needed
712
720
uint16 count = m_MaxBlockRequests - m_PendingBlocks_list.size();
713
std::vector<Requested_Block_Struct*> toadd(count);
714
if (m_reqfile->GetNextRequestedBlock(this,&(toadd[0]),&count)) {
721
std::vector<Requested_Block_Struct*> toadd;
722
if (m_reqfile->GetNextRequestedBlock(this, toadd, count)) {
715
723
for (int i = 0; i != count; i++) {
716
724
m_DownloadBlocks_list.push_back(toadd[i]);
804
814
wxASSERT(m_DownloadBlocks_list.empty());
805
815
wxASSERT(m_PendingBlocks_list.empty());
806
816
uint16 count = m_MaxBlockRequests;
807
std::vector<Requested_Block_Struct*> toadd(count);
808
if (m_reqfile->GetNextRequestedBlock(this, &(toadd[0]),&count)) {
817
std::vector<Requested_Block_Struct*> toadd;
818
if (m_reqfile->GetNextRequestedBlock(this, toadd, count)) {
809
819
for (int i = 0; i != count; i++) {
810
820
Pending_Block_Struct* pblock = new Pending_Block_Struct;
811
821
pblock->block = toadd[i];
1317
// Emilio: rewrite of eMule code to eliminate use of lists for averaging and fix
1318
// errors in calculation (32-bit rollover and time measurement) This function
1319
// uses a first-order filter with variable time constant (initially very short
1320
// to quickly reach the right value without spiking, then gradually approaching
1321
// the value of 50 seconds which is equivalent to the original averaging period
1322
// used in eMule). The download rate is measured using actual timestamps. The
1323
// filter-based averaging however uses a simplified algorithm that assumes a
1324
// fixed loop time - this does not introduce any measurement error, it simply
1325
// makes the degree of smoothing slightly imprecise (the true TC of the filter
1326
// varies inversely with the true loop time), which is of no importance here.
1335
// Speed is now updated only when data was received, calculated as
1336
// (data received) / (time since last receiption)
1337
// and slightly filtered (10s average).
1338
// Result is quite precise now and makes the DownloadRateAdjust workaround obsolete.
1328
1340
float CUpDownClient::CalculateKBpsDown()
1330
// -- all timing values are in seconds --
1331
const float tcLoop = 0.1f; // _assumed_ Process() loop time = 0.1 sec
1332
const float tcInit = 0.4f; // initial filter time constant
1333
const float tcFinal = 50.0f; // final filter time constant
1334
const float tcReduce = 5.0f; // transition from tcInit to tcFinal
1336
const float fInit = tcLoop/tcInit; // initial averaging factor
1337
const float fFinal = tcLoop/tcFinal; // final averaging factor
1338
const float fReduce = std::exp(std::log(fFinal/fInit) / (tcReduce/tcLoop)) * 0.99999;
1340
uint32 msCur = ::GetTickCount();
1342
const float tAverage = 10.0;
1343
uint32 msCur = GetTickCount();
1342
if (msReceivedPrev == 0) { // initialize the averaging filter
1343
fDownAvgFilter = fInit;
1344
// "kBpsDown = bytesReceivedCycle/1024.0 / tcLoop" would be technically correct,
1345
// but the first loop often receives a large chunk of data and then produces a spike
1346
kBpsDown = /* 0.0 * (1.0-fInit) + */ bytesReceivedCycle/1024.0 / tcLoop * fInit;
1347
bytesReceivedCycle = 0;
1348
} else if (msCur != msReceivedPrev) { // (safeguard against divide-by-zero)
1349
if (fDownAvgFilter > fFinal) { // reduce time constant during ramp-up phase
1350
fDownAvgFilter *= fReduce; // this approximates averaging a lengthening list
1352
kBpsDown = kBpsDown * (1.0 - fDownAvgFilter)
1353
+ (bytesReceivedCycle/1.024)/((float)(msCur-msReceivedPrev)) * fDownAvgFilter;
1354
bytesReceivedCycle = 0;
1345
if (bytesReceivedCycle) {
1346
float dt = (msCur - msReceivedPrev) / 1000.0; // time since last reception
1347
if (dt < 0.01) { // (safeguard against divide-by-zero)
1348
dt = 0.01f; // diff should be 100ms actually
1350
float kBpsDownCur = bytesReceivedCycle / 1024.0 / dt;
1351
if (dt >= tAverage) {
1352
kBpsDown = kBpsDownCur;
1354
kBpsDown = (kBpsDown * (tAverage - dt) + kBpsDownCur * dt) / tAverage;
1356
AddDebugLogLineM( false, logLocalClient, CFormat(wxT("CalculateKBpsDown %p kbps %.1f kbpsCur %.1f dt %.3f rcv %d "))
1357
% this % kBpsDown % kBpsDownCur % dt % bytesReceivedCycle);
1358
bytesReceivedCycle = 0;
1359
msReceivedPrev = msCur;
1356
msReceivedPrev = msCur;
1359
1363
if (m_cShowDR == 30){
1361
1365
UpdateDisplayedInfo();
1363
if ((::GetTickCount() - m_dwLastBlockReceived) > DOWNLOADTIMEOUT){
1367
if (msCur - m_dwLastBlockReceived > DOWNLOADTIMEOUT) {
1364
1368
if (!GetSentCancelTransfer()){
1365
1369
CPacket* packet = new CPacket(OP_CANCELTRANSFER, 0, OP_EDONKEYPROT);
1366
1370
theStats::AddUpOverheadFileRequest(packet->GetPacketSize());