remove the concept of slots, and just talk about pieces (since we don't do compact allocation anymore). Remove the section about compact allocation
This commit is contained in:
parent
9bed3d1dd5
commit
cec6748e0c
|
@ -394,10 +394,6 @@ The file format is a bencoded dictionary containing the following fields:
|
|||
| | means it is free, that there's no piece there. If it is -1, |
|
||||
| | means the slot isn't allocated on disk yet. The pieces have |
|
||||
| | to meet the following requirement: |
|
||||
| | |
|
||||
| | If there's a slot at the position of the piece index, |
|
||||
| | the piece must be located in that slot. |
|
||||
| | |
|
||||
+--------------------------+--------------------------------------------------------------+
|
||||
| ``total_uploaded`` | integer. The number of bytes that have been uploaded in |
|
||||
| | total for this torrent. |
|
||||
|
@ -579,61 +575,6 @@ The benefits of this mode are:
|
|||
* No risk of a download failing because of a full disk during download, once
|
||||
all files have been created.
|
||||
|
||||
compact allocation
|
||||
------------------
|
||||
|
||||
.. note::
|
||||
Support for compact allocation has been removed from libttorrent
|
||||
|
||||
The compact allocation will only allocate as much storage as it needs to keep
|
||||
the pieces downloaded so far. This means that pieces will be moved around to be
|
||||
placed at their final position in the files while downloading (to make sure the
|
||||
completed download has all its pieces in the correct place). So, the main
|
||||
drawbacks are:
|
||||
|
||||
* More disk operations while downloading since pieces are moved around.
|
||||
|
||||
* Potentially more fragmentation in the filesystem.
|
||||
|
||||
* Cannot be used while having files with priority 0.
|
||||
|
||||
The benefits though, are:
|
||||
|
||||
* No startup delay, since the files don't need allocating.
|
||||
|
||||
* The download will not use unnecessary disk space.
|
||||
|
||||
* Disk caches perform much better than in full allocation and raises the
|
||||
download speed limit imposed by the disk.
|
||||
|
||||
* Works well on filesystems that don't support sparse files.
|
||||
|
||||
The algorithm that is used when allocating pieces and slots isn't very
|
||||
complicated. For the interested, a description follows.
|
||||
|
||||
storing a piece:
|
||||
|
||||
1. let **A** be a newly downloaded piece, with index **n**.
|
||||
2. let **s** be the number of slots allocated in the file we're
|
||||
downloading to. (the number of pieces it has room for).
|
||||
3. if **n** >= **s** then allocate a new slot and put the piece there.
|
||||
4. if **n** < **s** then allocate a new slot, move the data at
|
||||
slot **n** to the new slot and put **A** in slot **n**.
|
||||
|
||||
allocating a new slot:
|
||||
|
||||
1. if there's an unassigned slot (a slot that doesn't
|
||||
contain any piece), return that slot index.
|
||||
2. append the new slot at the end of the file (or find an unused slot).
|
||||
3. let **i** be the index of newly allocated slot
|
||||
4. if we have downloaded piece index **i** already (to slot **j**) then
|
||||
|
||||
1. move the data at slot **j** to slot **i**.
|
||||
2. return slot index **j** as the newly allocated free slot.
|
||||
|
||||
5. return **i** as the newly allocated slot.
|
||||
|
||||
|
||||
HTTP seeding
|
||||
============
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
v
|
||||
+--------------------------+
|
||||
| "piece_manager" |
|
||||
| "(maps pieces to slots)" |
|
||||
| "disk job fence logic" |
|
||||
+--------------------------+
|
||||
^
|
||||
|
|
||||
|
@ -15,13 +15,13 @@
|
|||
/----------------------------\ +-------------------+
|
||||
| "storage" |<---->| "file_pool" |
|
||||
| | | "open file cache" |
|
||||
| "(maps slots to file and" | +-------------------+
|
||||
| "(maps pieces to file and" | +-------------------+
|
||||
| "offset. reads and writes" |
|
||||
| "to disk)" | +--------------------+
|
||||
| |<-----+ "file_storage" |
|
||||
\----------------------------/ | "standard slot to" |
|
||||
^ | "file mapping" |
|
||||
| +--------------------+
|
||||
| "to disk)" | +---------------------+
|
||||
| |<-----+ "file_storage" |
|
||||
\----------------------------/ | "standard piece to" |
|
||||
^ | "file mapping" |
|
||||
| +---------------------+
|
||||
v
|
||||
+--------------------------+
|
||||
| "file" |
|
||||
|
|
|
@ -90,9 +90,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
// temp_storage(file_storage const& fs) : m_files(fs) {}
|
||||
// virtual bool initialize(storage_error& se) { return false; }
|
||||
// virtual bool has_any_file() { return false; }
|
||||
// virtual int read(char* buf, int slot, int offset, int size)
|
||||
// virtual int read(char* buf, int piece, int offset, int size)
|
||||
// {
|
||||
// std::map<int, std::vector<char> >::const_iterator i = m_file_data.find(slot);
|
||||
// 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;
|
||||
|
@ -100,9 +100,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
// memcpy(buf, &i->second[offset], available);
|
||||
// return available;
|
||||
// }
|
||||
// virtual int write(const char* buf, int slot, int offset, int size)
|
||||
// virtual int write(const char* buf, int piece, int offset, int size)
|
||||
// {
|
||||
// std::vector<char>& data = m_file_data[slot];
|
||||
// std::vector<char>& data = m_file_data[piece];
|
||||
// if (data.size() < offset + size) data.resize(offset + size);
|
||||
// std::memcpy(&data[offset], buf, size);
|
||||
// return size;
|
||||
|
@ -114,15 +114,15 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
// , std::vector<std::string> const* links
|
||||
// , storage_error& error) { return false; }
|
||||
// virtual bool write_resume_data(entry& rd) const { return false; }
|
||||
// virtual boost::int64_t physical_offset(int slot, int offset)
|
||||
// { return slot * m_files.piece_length() + offset; };
|
||||
// virtual sha1_hash hash_for_slot(int slot, partial_hash& ph, int piece_size)
|
||||
// virtual boost::int64_t physical_offset(int piece, int offset)
|
||||
// { return piece * m_files.piece_length() + offset; };
|
||||
// virtual sha1_hash hash_for_slot(int piece, partial_hash& ph, int piece_size)
|
||||
// {
|
||||
// int left = piece_size - ph.offset;
|
||||
// assert(left >= 0);
|
||||
// if (left > 0)
|
||||
// {
|
||||
// std::vector<char>& data = m_file_data[slot];
|
||||
// std::vector<char>& data = m_file_data[piece];
|
||||
// // if there are padding files, those blocks will be considered
|
||||
// // completed even though they haven't been written to the storage.
|
||||
// // in this case, just extend the piece buffer to its full size
|
||||
|
@ -202,9 +202,10 @@ namespace libtorrent
|
|||
// but modifies some particular behavior, for instance encrypting the data
|
||||
// before it's written to disk, and decrypting it when it's read again.
|
||||
//
|
||||
// The storage interface is based on slots, each slot is 'piece_size' number
|
||||
// The storage interface is based on pieces. Avery read and write operation
|
||||
// happens in the piece-space. Each piece fits 'piece_size' number
|
||||
// of bytes. All access is done by writing and reading whole or partial
|
||||
// slots. One slot is one piece in the torrent.
|
||||
// pieces.
|
||||
//
|
||||
// libtorrent comes with two built-in storage implementations;
|
||||
// ``default_storage`` and ``disabled_storage``. Their constructor functions
|
||||
|
@ -466,7 +467,7 @@ namespace libtorrent
|
|||
};
|
||||
|
||||
void delete_one_file(std::string const& p, error_code& ec);
|
||||
int readwritev(file::iovec_t const* bufs, int slot, int offset
|
||||
int readwritev(file::iovec_t const* bufs, int piece, int offset
|
||||
, int num_bufs, fileop const& op, storage_error& ec);
|
||||
|
||||
void need_partfile();
|
||||
|
@ -477,7 +478,7 @@ namespace libtorrent
|
|||
// in order to avoid calling stat() on each file multiple times
|
||||
// during startup, cache the results in here, and clear it all
|
||||
// out once the torrent starts (to avoid getting stale results)
|
||||
// each slot represents the size and timestamp of the file
|
||||
// each entry represents the size and timestamp of the file
|
||||
mutable stat_cache m_stat_cache;
|
||||
|
||||
// helper function to open a file in the file pool with the right mode
|
||||
|
|
|
@ -714,12 +714,12 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
int default_storage::sparse_end(int slot) const
|
||||
int default_storage::sparse_end(int piece) const
|
||||
{
|
||||
TORRENT_ASSERT(slot >= 0);
|
||||
TORRENT_ASSERT(slot < files().num_pieces());
|
||||
TORRENT_ASSERT(piece >= 0);
|
||||
TORRENT_ASSERT(piece < files().num_pieces());
|
||||
|
||||
boost::int64_t file_offset = boost::int64_t(slot) * files().piece_length();
|
||||
boost::int64_t file_offset = boost::int64_t(piece) * files().piece_length();
|
||||
int file_index = 0;
|
||||
|
||||
for (;;)
|
||||
|
@ -734,7 +734,7 @@ namespace libtorrent
|
|||
|
||||
error_code ec;
|
||||
file_handle handle = open_file_impl(file_index, file::read_only, ec);
|
||||
if (ec) return slot;
|
||||
if (ec) return piece;
|
||||
|
||||
boost::int64_t data_start = handle->sparse_end(file_offset);
|
||||
return int((data_start + files().piece_length() - 1) / files().piece_length());
|
||||
|
@ -1096,7 +1096,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
int default_storage::readv(file::iovec_t const* bufs, int num_bufs
|
||||
, int slot, int offset, int flags, storage_error& ec)
|
||||
, int piece, int offset, int flags, storage_error& ec)
|
||||
{
|
||||
fileop op = { &file::readv
|
||||
, file::read_only | flags };
|
||||
|
@ -1104,15 +1104,15 @@ namespace libtorrent
|
|||
boost::thread::sleep(boost::get_system_time()
|
||||
+ boost::posix_time::milliseconds(1000));
|
||||
#endif
|
||||
return readwritev(bufs, slot, offset, num_bufs, op, ec);
|
||||
return readwritev(bufs, piece, offset, num_bufs, op, ec);
|
||||
}
|
||||
|
||||
int default_storage::writev(file::iovec_t const* bufs, int num_bufs
|
||||
, int slot, int offset, int flags, storage_error& ec)
|
||||
, int piece, int offset, int flags, storage_error& ec)
|
||||
{
|
||||
fileop op = { &file::writev
|
||||
, file::read_write | flags };
|
||||
return readwritev(bufs, slot, offset, num_bufs, op, ec);
|
||||
return readwritev(bufs, piece, offset, num_bufs, op, ec);
|
||||
}
|
||||
|
||||
// much of what needs to be done when reading and writing
|
||||
|
@ -1121,12 +1121,12 @@ namespace libtorrent
|
|||
// is a template, and the fileop decides what to do with the
|
||||
// file and the buffers.
|
||||
int default_storage::readwritev(file::iovec_t const* const bufs
|
||||
, const int slot, const int offset
|
||||
, const int piece, const int offset
|
||||
, const int num_bufs, fileop const& op, storage_error& ec)
|
||||
{
|
||||
TORRENT_ASSERT(bufs != 0);
|
||||
TORRENT_ASSERT(slot >= 0);
|
||||
TORRENT_ASSERT(slot < m_files.num_pieces());
|
||||
TORRENT_ASSERT(piece >= 0);
|
||||
TORRENT_ASSERT(piece < m_files.num_pieces());
|
||||
TORRENT_ASSERT(offset >= 0);
|
||||
TORRENT_ASSERT(num_bufs > 0);
|
||||
|
||||
|
@ -1135,7 +1135,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(files().is_loaded());
|
||||
|
||||
// find the file iterator and file offset
|
||||
boost::uint64_t torrent_offset = slot * boost::uint64_t(m_files.piece_length()) + offset;
|
||||
boost::uint64_t torrent_offset = piece * boost::uint64_t(m_files.piece_length()) + offset;
|
||||
int file_index = files().file_index_at_offset(torrent_offset);
|
||||
TORRENT_ASSERT(torrent_offset >= files().file_offset(file_index));
|
||||
TORRENT_ASSERT(torrent_offset < files().file_offset(file_index) + files().file_size(file_index));
|
||||
|
@ -1229,13 +1229,13 @@ namespace libtorrent
|
|||
// the fileop object.
|
||||
// write
|
||||
bytes_transferred = m_part_file->writev(tmp_bufs, num_tmp_bufs
|
||||
, slot, offset, e);
|
||||
, piece, offset, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
// read
|
||||
bytes_transferred = m_part_file->readv(tmp_bufs, num_tmp_bufs
|
||||
, slot, offset, e);
|
||||
, piece, offset, e);
|
||||
}
|
||||
if (e)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue