libtorrent - storage_interface 阅读说明
libtorrent - storage_interface readv explanation
我已经按照帮助部分中的描述在 libtorrent 中实现了自定义存储接口 here。
storage_interface 工作正常,虽然我不明白为什么 readv
只在下载 torrent 时随机调用。在我看来,每次我在 piece_finished_alert
中调用 handle->read_piece
时,应该调用覆盖的虚函数 readv
。它应该阅读 read_piece_alert?
的文章
缓冲区在 read_piece_alert
中提供,但在 readv
中未得到通知。
所以问题是为什么它只是随机调用而不是在 read_piece()
调用中调用?我的 storage_interface 可能是错的吗?
代码如下所示:
struct temp_storage : storage_interface
{
virtual int readv(file::iovec_t const* bufs, int num_bufs
, int piece, int offset, int flags, storage_error& ec)
{
// Only called on random pieces while downloading a larger torrent
std::map<int, std::vector<char> >::const_iterator i = m_file_data.find(piece);
if (i == m_file_data.end()) return 0;
int available = i->second.size() - offset;
if (available <= 0) return 0;
if (available > num_bufs) available = num_bufs;
memcpy(&bufs, &i->second[offset], available);
return available;
}
virtual int writev(file::iovec_t const* bufs, int num_bufs
, int piece, int offset, int flags, storage_error& ec)
{
std::vector<char>& data = m_file_data[piece];
if (data.size() < offset + num_bufs) data.resize(offset + num_bufs);
std::memcpy(&data[offset], bufs, num_bufs);
return num_bufs;
}
virtual bool has_any_file(storage_error& ec) { return false; }
virtual ...
virtual ...
}
初始化为
storage_interface* temp_storage_constructor(storage_params const& params)
{
printf("NEW INTERFACE\n");
return new temp_storage(*params.files);
}
p.storage = &temp_storage_constructor;
下面的函数设置警报并在每个完成的片段上调用 read_piece
。
while(true) {
std::vector<alert*> alerts;
s.pop_alerts(&alerts);
for (alert* i : alerts)
{
switch (i->type()) {
case read_piece_alert::alert_type:
{
read_piece_alert* p = (read_piece_alert*)i;
if (p->ec) {
// read_piece failed
break;
}
// piece buffer, size is provided without readv
// notification after invoking read_piece in piece_finished_alert
break;
}
case piece_finished_alert::alert_type: {
piece_finished_alert* p = (piece_finished_alert*)i;
p->handle.read_piece(p->piece_index);
// Once the piece is finished, we read it to obtain the buffer in read_piece_alert.
break;
}
default:
break;
}
}
Sleep(100);
}
我会回答我自己的问题。正如 Arvid 在评论中所说: readv
由于缓存而未被调用。将 settings_pack::use_read_cache
设置为 false 将始终调用 readv
。
我已经按照帮助部分中的描述在 libtorrent 中实现了自定义存储接口 here。
storage_interface 工作正常,虽然我不明白为什么 readv
只在下载 torrent 时随机调用。在我看来,每次我在 piece_finished_alert
中调用 handle->read_piece
时,应该调用覆盖的虚函数 readv
。它应该阅读 read_piece_alert?
缓冲区在 read_piece_alert
中提供,但在 readv
中未得到通知。
所以问题是为什么它只是随机调用而不是在 read_piece()
调用中调用?我的 storage_interface 可能是错的吗?
代码如下所示:
struct temp_storage : storage_interface
{
virtual int readv(file::iovec_t const* bufs, int num_bufs
, int piece, int offset, int flags, storage_error& ec)
{
// Only called on random pieces while downloading a larger torrent
std::map<int, std::vector<char> >::const_iterator i = m_file_data.find(piece);
if (i == m_file_data.end()) return 0;
int available = i->second.size() - offset;
if (available <= 0) return 0;
if (available > num_bufs) available = num_bufs;
memcpy(&bufs, &i->second[offset], available);
return available;
}
virtual int writev(file::iovec_t const* bufs, int num_bufs
, int piece, int offset, int flags, storage_error& ec)
{
std::vector<char>& data = m_file_data[piece];
if (data.size() < offset + num_bufs) data.resize(offset + num_bufs);
std::memcpy(&data[offset], bufs, num_bufs);
return num_bufs;
}
virtual bool has_any_file(storage_error& ec) { return false; }
virtual ...
virtual ...
}
初始化为
storage_interface* temp_storage_constructor(storage_params const& params)
{
printf("NEW INTERFACE\n");
return new temp_storage(*params.files);
}
p.storage = &temp_storage_constructor;
下面的函数设置警报并在每个完成的片段上调用 read_piece
。
while(true) {
std::vector<alert*> alerts;
s.pop_alerts(&alerts);
for (alert* i : alerts)
{
switch (i->type()) {
case read_piece_alert::alert_type:
{
read_piece_alert* p = (read_piece_alert*)i;
if (p->ec) {
// read_piece failed
break;
}
// piece buffer, size is provided without readv
// notification after invoking read_piece in piece_finished_alert
break;
}
case piece_finished_alert::alert_type: {
piece_finished_alert* p = (piece_finished_alert*)i;
p->handle.read_piece(p->piece_index);
// Once the piece is finished, we read it to obtain the buffer in read_piece_alert.
break;
}
default:
break;
}
}
Sleep(100);
}
我会回答我自己的问题。正如 Arvid 在评论中所说: readv
由于缓存而未被调用。将 settings_pack::use_read_cache
设置为 false 将始终调用 readv
。