qbittorrent / qBittorrent

qBittorrent BitTorrent client
https://www.qbittorrent.org
Other
27.79k stars 3.92k forks source link

Move partfile with completed files when setting location. #12760

Open Ryrynz opened 4 years ago

Ryrynz commented 4 years ago

If I set a location to move a torrent that has been partially completed the partfile still exists in the original folder location. The partfile belongs to a file within the torrent that has been unticked so it is not downloaded, I assume this is why it was not moved.

Are partfiles seeded at all? And if the file is belongs to is unticked is it still used for seeding? If they are then it makes sense to keep all available downloaded data together.

FranciscoPombal commented 4 years ago

Hmm, seems to me the .part file should be moved as well. @glassez thoughts?

Are partfiles seeded at all? And if the file is belongs to is unticked is it still used for seeding?

I would expect the pieces in the .part file that also belong to other files that are "ticked" to be able to be seeded still. But I think you'll obtain a better answer from @arvidn.

arvidn commented 4 years ago

yes, the contents of part files are partial pieces whose other part belong to a file that was "selected". In order to seed every byte in those files, the partial pieces are also necessary. Otherwise downloaders cannot check the piece hashes.

The part file should definitely be moved along with the rest of the storage.

This is the function in libtorrent called in the disk thread when moving storage for a torrent: https://github.com/arvidn/libtorrent/blob/RC_1_2/src/storage.cpp#L511

The bulk of the logic is factored out into a, somewhat, generic function, here: https://github.com/arvidn/libtorrent/blob/RC_1_2/src/storage_utils.cpp#L204

If there are no errors moving the main files, the file storage is moved here: https://github.com/arvidn/libtorrent/blob/RC_1_2/src/storage_utils.cpp#L318

That function is implemented here: https://github.com/arvidn/libtorrent/blob/RC_1_2/src/part_file.cpp#L256

The condition to do anything there is !m_piece_map.empty(), that being empty means there's nothing in the part file, so it's not moved in that case.

FranciscoPombal commented 4 years ago

@arvidn

The condition to do anything there is !m_piece_map.empty(), that being empty means there's nothing in the part file, so it's not moved in that case.

What if the .partfile gets created, but not written to, before the user decides to move (can this happen at all?)? Then it will not be moved, correct? And in that case, will the part pieces will be written to the old location, or will they be written to the new location, and leave the old 0 bytes .part file behind?

arvidn commented 4 years ago

What if the .partfile gets created, but not written to, before the user decides to move (can this happen at all?)? Then it will not be moved, correct? And in that case, will the part pieces will be written to the old location, or will they be written to the new location, and leave the old 0 bytes .part file behind?

I'm not sure it can happen in practice. The case I can think of is a file being "deselected" at first, and then selected after some parts have been written to the file. Those parts will then be moved out of the part file, and it may exist on disk but not contain any data.

In that case, it will be left behind, but if the part file is needed again, a new one will be created in the new storage location.

glassez commented 4 years ago

In that case, it will be left behind, but if the part file is needed again, a new one will be created in the new storage location.

Looks like a bug to me. If partfile was created it should be either deleted once it become unneeded (i.e. when all parts are moved out of there) or remain handled by torrent storage.