Discussion:
[libtorrent] Pad file parameters does not work in some cases.
Trung Thanh Tran
2016-07-05 15:55:11 UTC
Permalink
Hi,
I have met problem with pad file in libtorrent-python. I did my test in 1.0.6, 1.0.7, 1.1.0.

Use case:
Share a directory containing 5 files
- a-0000.rs size ~501MB
- a-0001.rs size ~501MB
- a-0002.rs size ~501MB
- a-0003.rs size ~501MB
- a-info.txt size ~48 bytes

Now, I need to create torrent which allows me to download a file with specific index e.g. a-0001.rs and a-info.text

I have implement the following snippet to create torrent
# Start generate torrent
def generate_torrent(shared_directory, piece_size=0,
pad_size_limit=16 * 1024, flags=1):

file_storage = lt.file_storage()
if piece_size % 16384 is not 0:
self.logger.warn('Torrent piece size must be 0 or a multiple of 16 kiB.')
piece_size = 16384 # 16 kib
directory = os.path.abspath(sharing_resource)
parent_directory = os.path.split(directory)[0]
for root, dirs, files in os.walk(directory):
if os.path.split(root)[1][0] == '.':
continue
for f in files:
if f[0] in ['.', 'Thumbs.db']:
continue
filename = os.path.join(root[len(parent_directory) + 1:], f)
size = os.path.getsize(os.path.join(parent_directory, filename))
file_storage.add_file(filename, size)
torrent = lt.create_torrent(file_storage, piece_size, pad_size_limit, flags)
lt.set_piece_hashes(torrent, parent_directory)
torrent = torrent.generate()
file_to_store.write(lt.bencode(torrent))
file_to_store.close()
# End generate torrent
And following code to download to download specific index
# Start download torrent
num_file = info.num_files()
file_priorities = list()
file_list = dict()
info_index = -1
for index in range(num_file):
current_path = info.file_at(index).path
self.logger.debug("Include " + current_path + " at index = " + str(index) + " to get")
if "-info.txt" in current_path:
file_priorities.append(7)
info_index = index
elif ".rs" in current_path:
file_list[index] = current_path
file_priorities.append(7)
else:
file_priorities.append(0)
add_torrent_params = dict()
add_torrent_params['ti'] = info
add_torrent_params['save_path'] = destination_directory
add_torrent_params['storage_mode'] = lt.storage_mode_t.storage_mode_sparse
try:
resume_path = ''.join([destination_directory, info.name(), '.fastresume'])
add_torrent_params['resume_data'] = open(os.path.join(resume_path), 'rb').read()
except:
pass
torrent_handler = libtorrent_session.add_torrent(add_torrent_params)
torrent_handler.prioritize_files(file_priorities)
# End download torrent
When I try to use 2 snippets above, the result is unstable.
- Try to download index =0, I see that a-0000.rs, a-info.txt and a-0001.rs are in target.
Afterthat, when varying the size of rs file, sometimes all files are in the target although only index 1 is marked to be downloaded.
Please correct me if I implement incorrectly pad files.

Thanks and best regards,
Thanh,
Arvid Norberg
2016-07-05 22:06:20 UTC
Permalink
Post by Trung Thanh Tran
Hi,
I have met problem with pad file in libtorrent-python. I did my test in
1.0.6, 1.0.7, 1.1.0.
Share a directory containing 5 files
- a-0000.rs size ~501MB
- a-0001.rs size ~501MB
- a-0002.rs size ~501MB
- a-0003.rs size ~501MB
- a-info.txt size ~48 bytes
Now, I need to create torrent which allows me to download a file with
specific index e.g. a-0001.rs and a-info.text
To narrow down the problem, it would make sense to look at the .torrent
file you generate, to see if it looks correct. For instance, do all files
start on a piece boundary? I take it that's what you're aiming for.

My guess is that the small 48 byte file will be used as padding for another
large file. When you download that file, you'll likely also pull down a
part of another larger file.
--
Arvid Norberg
Arvid Norberg
2016-07-07 03:32:03 UTC
Permalink
dump_torrent confirms the statement I made in my last email:

0 204425456 ---- [ 0, 389 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/
cocos2d-x-2.2.6.zip-0000.rs
c2f48f0 54 ---- [ 389, 389 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/cocos2d-x-2.2.6.zip-info.txt
c2f4926 46810 p--- [ 389, 389 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/.____padding_file/0
c300000 204425456 ---- [ 390, 779 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/
cocos2d-x-2.2.6.zip-0003.rs
185f48f0 46864 p--- [ 779, 779 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/.____padding_file/1
18600000 204425456 ---- [ 780, 1169 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/
cocos2d-x-2.2.6.zip-0002.rs
248f48f0 46864 p--- [ 1169, 1169 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/.____padding_file/2
24900000 204425456 ---- [ 1170, 1559 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/
cocos2d-x-2.2.6.zip-0001.rs

Now, presumably you did not expect the torrent to be created like this.
Please provide the parameters you passed to the torrent creation and what
effect you expected them to have.
Hi,
@Arvid
I attach two torrent files created by my example.
Thanks for your response. I copied wrong snippet. The correct one is below
e = lt.bdecode(open(torrent_path, 'rb').read())
info = lt.torrent_info(e)
num_file = info.num_files()
file_priorities = list()
file_list = dict()
peer_piece = piece_index
return None
current_path = info.file_at(index).path
self.logger.debug("Include " + current_path + " at index = " + str(index) + " to seeding")
file_priorities.append(7)
self.logger.debug("Include " + current_path + " at index = " + str(index) + " to seeding")
file_priorities.append(7)
file_list[index] = current_path
self.logger.debug("Exclude " + current_path + " at index = " + str(index) + " to seeding")
file_list[index] = current_path
file_priorities.append(0)
self.logger.debug("Exclude " + current_path + " at index = " + str(index) + " to seeding")
file_priorities.append(0)
add_torrent_params = dict()
add_torrent_params['ti'] = info
add_torrent_params['save_path'] = self.seeds_directory
add_torrent_params['storage_mode'] = lt.storage_mode_t.storage_mode_sparse
resume_path = ''.join([self.seeds_directory, info.name(), '.fastresume'])
add_torrent_params['resume_data'] = open(os.path.join(resume_path), 'rb').read()
pass
self.logger.debug("Start leeching %s" % torrent_path)
torrent_handler = self.ses.add_torrent(add_torrent_params)
torrent_handler.prioritize_files(file_priorities)
Best regards,
Hi,
I have met problem with pad file in libtorrent-python. I did my test in
1.0.6, 1.0.7, 1.1.0.
Share a directory containing 5 files
- a-0000.rs size ~501MB
- a-0001.rs size ~501MB
- a-0002.rs size ~501MB
- a-0003.rs size ~501MB
- a-info.txt size ~48 bytes
Now, I need to create torrent which allows me to download a file with
specific index e.g. a-0001.rs and a-info.text
To narrow down the problem, it would make sense to look at the .torrent
file you generate, to see if it looks correct. For instance, do all files
start on a piece boundary? I take it that's what you're aiming for.
My guess is that the small 48 byte file will be used as padding for another
large file. When you download that file, you'll likely also pull down a
part of another larger file.
--
Arvid Norberg
------------------------------------------------------------------------------
Attend Shape: An AT&T Tech Expo July 15-16. Meet us at AT&T Park in San
Francisco, CA to explore cutting-edge tech and listen to tech luminaries
present their vision of the future. This family event has something for
everyone, including kids. Get more information and register today.
http://sdm.link/attshape
_______________________________________________
Libtorrent-discuss mailing list
https://lists.sourceforge.net/lists/listinfo/libtorrent-discuss
--
Arvid Norberg
Trung Thành Trần
2016-07-07 04:56:49 UTC
Permalink
Hi,

Here is the snippet to create torrent

# Start generate torrent

def generate_torrent(shared_directory, piece_size=0,
pad_size_limit=16 * 1024, flags=1):



file_storage = lt.file_storage()
if piece_size % 16384 is not 0:
self.logger.warn('Torrent piece size must be 0 or a multiple of 16 kiB.')
piece_size = 16384 # 16 kib

directory = os.path.abspath(sharing_resource)

parent_directory = os.path.split(directory)[0]
for root, dirs, files in os.walk(directory):
if os.path.split(root)[1][0] == '.':
continue
for f in files:
if f[0] in ['.', 'Thumbs.db']:
continue
filename = os.path.join(root[len(parent_directory) + 1:], f)
size = os.path.getsize(os.path.join(parent_directory, filename))
file_storage.add_file(filename, size)
torrent = lt.create_torrent(file_storage, piece_size, pad_size_limit, flags)

lt.set_piece_hashes(torrent, parent_directory)
torrent = torrent.generate()

file_to_store.write(lt.bencode(torrent))

file_to_store.close()

# End generate torrent


My expected is that all rs files and info file are fitted in pieces. For example

test-0000.rs + padding in [0,x]

test-0001.rs + padding in [x+1,2x]

test-0002.rs + padding in [2x+1,3x]

test-0003.rs + padding in [3x+1,4x]

test-info.txt + padding in [4x+1, 4x+n]

Best regards,
Post by Arvid Norberg
0 204425456 ---- [ 0, 389 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/
cocos2d-x-2.2.6.zip-0000.rs
c2f48f0 54 ---- [ 389, 389 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/cocos2d-x-2.2.6.zip-info.txt
c2f4926 46810 p--- [ 389, 389 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/.____padding_file/0
c300000 204425456 ---- [ 390, 779 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/
cocos2d-x-2.2.6.zip-0003.rs
185f48f0 46864 p--- [ 779, 779 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/.____padding_file/1
18600000 204425456 ---- [ 780, 1169 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/
cocos2d-x-2.2.6.zip-0002.rs
248f48f0 46864 p--- [ 1169, 1169 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/.____padding_file/2
24900000 204425456 ---- [ 1170, 1559 ] 0
89e93729d4fea6b88882947e464a5495fc730e88ee60918f02262e8d7d82b799/
cocos2d-x-2.2.6.zip-0001.rs
Now, presumably you did not expect the torrent to be created like this.
Please provide the parameters you passed to the torrent creation and what
effect you expected them to have.
Hi,
@Arvid
I attach two torrent files created by my example.
Thanks for your response. I copied wrong snippet. The correct one is below
e = lt.bdecode(open(torrent_path, 'rb').read())
info = lt.torrent_info(e)
num_file = info.num_files()
file_priorities = list()
file_list = dict()
peer_piece = piece_index
return None
current_path = info.file_at(index).path
self.logger.debug("Include " + current_path + " at index = " + str(index) + " to seeding")
file_priorities.append(7)
self.logger.debug("Include " + current_path + " at index = " + str(index) + " to seeding")
file_priorities.append(7)
file_list[index] = current_path
self.logger.debug("Exclude " + current_path + " at index = " + str(index) + " to seeding")
file_list[index] = current_path
file_priorities.append(0)
self.logger.debug("Exclude " + current_path + " at index = " + str(index) + " to seeding")
file_priorities.append(0)
add_torrent_params = dict()
add_torrent_params['ti'] = info
add_torrent_params['save_path'] = self.seeds_directory
add_torrent_params['storage_mode'] = lt.storage_mode_t.storage_mode_sparse
resume_path = ''.join([self.seeds_directory, info.name(), '.fastresume'])
add_torrent_params['resume_data'] = open(os.path.join(resume_path), 'rb').read()
pass
self.logger.debug("Start leeching %s" % torrent_path)
torrent_handler = self.ses.add_torrent(add_torrent_params)
torrent_handler.prioritize_files(file_priorities)
Best regards,
Hi,
I have met problem with pad file in libtorrent-python. I did my test in
1.0.6, 1.0.7, 1.1.0.
Share a directory containing 5 files
- a-0000.rs size ~501MB
- a-0001.rs size ~501MB
- a-0002.rs size ~501MB
- a-0003.rs size ~501MB
- a-info.txt size ~48 bytes
Now, I need to create torrent which allows me to download a file with
specific index e.g. a-0001.rs and a-info.text
To narrow down the problem, it would make sense to look at the .torrent
file you generate, to see if it looks correct. For instance, do all files
start on a piece boundary? I take it that's what you're aiming for.
My guess is that the small 48 byte file will be used as padding for another
large file. When you download that file, you'll likely also pull down a
part of another larger file.
--
Arvid Norberg
------------------------------------------------------------------------------
Attend Shape: An AT&T Tech Expo July 15-16. Meet us at AT&T Park in San
Francisco, CA to explore cutting-edge tech and listen to tech luminaries
present their vision of the future. This family event has something for
everyone, including kids. Get more information and register today.
http://sdm.link/attshape
_______________________________________________
Libtorrent-discuss mailing list
https://lists.sourceforge.net/lists/listinfo/libtorrent-discuss
--
Arvid Norberg
Arvid Norberg
2016-07-07 05:32:36 UTC
Permalink
Post by Trung Thành Trần
Hi,
Here is the snippet to create torrent
# Start generate torrent
def generate_torrent(shared_directory, piece_size=0,
[...]
torrent = lt.create_torrent(file_storage, piece_size, pad_size_limit, flags)
flag 1 means optimize alignment, which is exactly what happens. The small
file will not be aligned, because it's smaller than the alignment
requirement (pad_size_limitt).

For other flags, see
http://libtorrent.org/reference-Create_Torrents.html#flags_t

Specifically, if you want every file to be padded and aligned
*unconditionally*, take a look at mutable_torrent_support. I believe that
will make it align everything to piece boundaries.
--
Arvid Norberg
Trung Thanh Tran
2016-07-12 12:58:15 UTC
Permalink
Hi,
I tried to generate torrent with all combinations of flag. Unluckily, there are only two cases which are far from my expectation.
- If pad files are added, small file is used as a pad file
- If small file is not used as a pad file, no pad file is generated.

Moreover, in libtorrent document, there is an instruction

If a pad_size_limit is specified (other than -1), any file larger than the specified number of bytes will be preceeded by a pad file to align it with the start of a piece. The pad_file_limit is ignored unless the optimize_alignment flag is passed. Typically it doesn't make sense to set this any lower than 4kiB.

If I do not misunderstand, optimize_flag must be on and my tiny file are also used as pad file.
Do you any suggestion to help me bypass my trouble,

Thanks and Best regards,

Thanh,
Post by Trung Thành Trần
Hi,
Here is the snippet to create torrent
# Start generate torrent
def generate_torrent(shared_directory, piece_size=0,
[...]
torrent = lt.create_torrent(file_storage, piece_size, pad_size_limit, flags)
flag 1 means optimize alignment, which is exactly what happens. The small file will not be aligned, because it's smaller than the alignment requirement (pad_size_limitt).
For other flags, see http://libtorrent.org/reference-Create_Torrents.html#flags_t <http://libtorrent.org/reference-Create_Torrents.html#flags_t>
Specifically, if you want every file to be padded and aligned *unconditionally*, take a look at mutable_torrent_support. I believe that will make it align everything to piece boundaries.
--
Arvid Norberg
Arvid Norberg
2016-07-12 21:48:08 UTC
Permalink
It sounds like it probably makes sense to apply that "pad_size_limit" when
picking files to be used as pad-files as well. Do you think you'd be up for
making that change and submitting a pull request?
Post by Trung Thanh Tran
Hi,
I tried to generate torrent with all combinations of flag. Unluckily,
there are only two cases which are far from my expectation.
- If pad files are added, small file is used as a pad file
- If small file is not used as a pad file, no pad file is generated.
Moreover, in libtorrent document, there is an instruction
If a pad_size_limit is specified (other than -1), any file larger than
the specified number of bytes will be preceeded by a pad file to align it
with the start of a piece. The pad_file_limit is ignored unless the
optimize_alignment flag is passed. Typically it doesn't make sense to set
this any lower than 4kiB.
If I do not misunderstand, optimize_flag must be on and my tiny file are
also used as pad file.
Do you any suggestion to help me bypass my trouble,
Thanks and Best regards,
Thanh,
Post by Trung Thành Trần
Hi,
Here is the snippet to create torrent
# Start generate torrent
def generate_torrent(shared_directory, piece_size=0,
[...]
torrent = lt.create_torrent(file_storage, piece_size, pad_size_limit, flags)
flag 1 means optimize alignment, which is exactly what happens. The small
file will not be aligned, because it's smaller than the alignment
requirement (pad_size_limitt).
For other flags, see
http://libtorrent.org/reference-Create_Torrents.html#flags_t
Specifically, if you want every file to be padded and aligned
*unconditionally*, take a look at mutable_torrent_support. I believe that
will make it align everything to piece boundaries.
--
Arvid Norberg
--
Arvid Norberg
Continue reading on narkive:
Loading...