Downloads not being counted correctly

enricodias4654

Member
YetiShare User
Jan 13, 2015
411
1
16
Problem:
If multiple users start the download of a single file at the same time, only one will be logged.

Solution:
Replace this line: $db->query('UPDATE file SET visits = :visits WHERE id = :id', array('visits' => $this->visits, 'id' => $this->id));
to this: $db->query('UPDATE file SET visits = visits + 1 WHERE id = :id', array('id' => $this->id));
in the file.class.php

Details:
The updateVisitors() method in the file class add +1 to $this->visits and then saves the value in the database without using transactions.
$this->visits is loaded in the beginning and updateVisitors() is called by the stats class at the end of the download when using pure php to serve the downloads.

Example and how to reproduce:
User A starts downloading file 1. $this->visits = 0.
User B starts downloading file 1. $this->visits = 0.
User A finish the download. $this->visits++; mysql query saving 1 to the visits field.
User B finish the download. $this->visits++; mysql query saving 1 to the visits field. Data from user A is lost.
 

enricodias4654

Member
YetiShare User
Jan 13, 2015
411
1
16
To update the file table with the correct values, run this query: UPDATE file SET visits = (SELECT count(*) as visits FROM stats WHERE file_id = file.id)

Don't forget to make a backup.
 

adam

Administrator
Staff member
Dec 5, 2009
2,043
108
63
Hi,

Thanks for reporting. This was caught a few weeks back and is ready for the next release. It should only happen with 2 files are overlapping on download and it wont happen when using xSendFile or xAccelRedirect.

Thanks for posting the query to update the db aswell.

Regards,
Adam.
 

enricodias4654

Member
YetiShare User
Jan 13, 2015
411
1
16
adam said:
Hi,

Thanks for reporting. This was caught a few weeks back and is ready for the next release. It should only happen with 2 files are overlapping on download and it wont happen when using xSendFile or xAccelRedirect.

Thanks for posting the query to update the db aswell.

Regards,
Adam.
I does happen using xSendile and xAccelRedirect, but not as often. There is a window of few milliseconds between getting the value from the db and sending the update. This window can be larger when using a mysql server in another datacenter, can be even some seconds.
 

adam

Administrator
Staff member
Dec 5, 2009
2,043
108
63
I've not seen it in the real world but sure it's possible. It's fixed for the next release.