attempted fix for inconsistent debug refcounters on blocks. pinning pieces with outstanding reads in an attempt at fixing inconsitencies seen around that logic as well
This commit is contained in:
parent
ad7d74f255
commit
9a2e511dda
|
@ -115,7 +115,6 @@ namespace libtorrent
|
||||||
: buf(0)
|
: buf(0)
|
||||||
, refcount(0)
|
, refcount(0)
|
||||||
, dirty(false)
|
, dirty(false)
|
||||||
, hitcount(0)
|
|
||||||
, pending(false)
|
, pending(false)
|
||||||
{
|
{
|
||||||
#if TORRENT_USE_ASSERTS
|
#if TORRENT_USE_ASSERTS
|
||||||
|
@ -127,7 +126,7 @@ namespace libtorrent
|
||||||
|
|
||||||
char* buf;
|
char* buf;
|
||||||
|
|
||||||
enum { max_refcount = (1 << 15) -1 };
|
enum { max_refcount = (1 << 30) - 1 };
|
||||||
|
|
||||||
// the number of references to this buffer. These references
|
// the number of references to this buffer. These references
|
||||||
// might be in outstanding asyncronous requests or in peer
|
// might be in outstanding asyncronous requests or in peer
|
||||||
|
@ -135,7 +134,7 @@ namespace libtorrent
|
||||||
// all references are gone and refcount reaches 0. The buf
|
// all references are gone and refcount reaches 0. The buf
|
||||||
// pointer in this struct doesn't count as a reference and
|
// pointer in this struct doesn't count as a reference and
|
||||||
// is always the last to be cleared
|
// is always the last to be cleared
|
||||||
boost::uint16_t refcount:15;
|
boost::uint32_t refcount:30;
|
||||||
|
|
||||||
// if this is true, this block needs to be written to
|
// if this is true, this block needs to be written to
|
||||||
// disk before it's freed. Typically all blocks in a piece
|
// disk before it's freed. Typically all blocks in a piece
|
||||||
|
@ -143,17 +142,13 @@ namespace libtorrent
|
||||||
// (read-ahead cache). Once blocks are written to disk, the
|
// (read-ahead cache). Once blocks are written to disk, the
|
||||||
// dirty flag is cleared and effectively turns the block
|
// dirty flag is cleared and effectively turns the block
|
||||||
// into a read cache block
|
// into a read cache block
|
||||||
boost::uint16_t dirty:1;
|
boost::uint32_t dirty:1;
|
||||||
|
|
||||||
// the number of times this block has been copied out of
|
|
||||||
// the cache, serving a request.
|
|
||||||
boost::uint16_t hitcount:15;
|
|
||||||
|
|
||||||
// pending means that this buffer has not yet been filled in
|
// pending means that this buffer has not yet been filled in
|
||||||
// with valid data. There's an outstanding read job for this.
|
// with valid data. There's an outstanding read job for this.
|
||||||
// If the dirty flag is set, it means there's an outstanding
|
// If the dirty flag is set, it means there's an outstanding
|
||||||
// write job to write this block.
|
// write job to write this block.
|
||||||
boost::uint16_t pending:1;
|
boost::uint32_t pending:1;
|
||||||
|
|
||||||
#if TORRENT_USE_ASSERTS
|
#if TORRENT_USE_ASSERTS
|
||||||
// this many of the references are held by hashing operations
|
// this many of the references are held by hashing operations
|
||||||
|
@ -179,6 +174,7 @@ namespace libtorrent
|
||||||
&& num_blocks == 0
|
&& num_blocks == 0
|
||||||
&& !hashing
|
&& !hashing
|
||||||
&& read_jobs.size() == 0
|
&& read_jobs.size() == 0
|
||||||
|
&& outstanding_read == 0
|
||||||
&& (ignore_hash || !hash || hash->offset == 0);
|
&& (ignore_hash || !hash || hash->offset == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,9 +205,11 @@ namespace libtorrent
|
||||||
|
|
||||||
// the pointers to the block data. If this is a ghost
|
// the pointers to the block data. If this is a ghost
|
||||||
// cache entry, there won't be any data here
|
// cache entry, there won't be any data here
|
||||||
// TODO: 3 could this be a scoped_array instead? does cached_piece_entry really need to be copyable?
|
|
||||||
// cached_piece_entry does need to be copyable since it's part of a container, but it's possible
|
// TODO: 3 could this be a scoped_array instead? does cached_piece_entry
|
||||||
// it could be a raw pointer or boost::unique_ptr perhaps
|
// really need to be copyable? cached_piece_entry does need to be
|
||||||
|
// copyable since it's part of a container, but it's possible it could be
|
||||||
|
// a raw pointer or boost::unique_ptr perhaps
|
||||||
boost::shared_array<cached_block_entry> blocks;
|
boost::shared_array<cached_block_entry> blocks;
|
||||||
|
|
||||||
// the last time a block was written to this piece
|
// the last time a block was written to this piece
|
||||||
|
|
|
@ -1281,6 +1281,8 @@ bool block_cache::inc_block_refcount(cached_piece_entry* pe, int block, int reas
|
||||||
case ref_reading: ++pe->blocks[block].reading_count; break;
|
case ref_reading: ++pe->blocks[block].reading_count; break;
|
||||||
case ref_flushing: ++pe->blocks[block].flushing_count; break;
|
case ref_flushing: ++pe->blocks[block].flushing_count; break;
|
||||||
};
|
};
|
||||||
|
TORRENT_ASSERT(pe->blocks[block].refcount >= pe->blocks[block].hashing_count
|
||||||
|
+ pe->blocks[block].reading_count + pe->blocks[block].flushing_count);
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1337,6 +1339,8 @@ void block_cache::dec_block_refcount(cached_piece_entry* pe, int block, int reas
|
||||||
case ref_reading: --pe->blocks[block].reading_count; break;
|
case ref_reading: --pe->blocks[block].reading_count; break;
|
||||||
case ref_flushing: --pe->blocks[block].flushing_count; break;
|
case ref_flushing: --pe->blocks[block].flushing_count; break;
|
||||||
};
|
};
|
||||||
|
TORRENT_PIECE_ASSERT(pe->blocks[block].refcount >= pe->blocks[block].hashing_count
|
||||||
|
+ pe->blocks[block].reading_count + pe->blocks[block].flushing_count, pe);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1603,6 +1607,12 @@ void block_cache::check_invariant() const
|
||||||
}
|
}
|
||||||
if (p.blocks[k].pending) ++num_pending;
|
if (p.blocks[k].pending) ++num_pending;
|
||||||
if (p.blocks[k].refcount > 0) ++num_pinned;
|
if (p.blocks[k].refcount > 0) ++num_pinned;
|
||||||
|
|
||||||
|
TORRENT_PIECE_ASSERT(p.blocks[k].refcount >=
|
||||||
|
p.blocks[k].hashing_count
|
||||||
|
+ p.blocks[k].reading_count
|
||||||
|
+ p.blocks[k].flushing_count, &p);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1678,9 +1688,6 @@ int block_cache::copy_from_piece(cached_piece_entry* pe, disk_io_job* j, bool ex
|
||||||
j->d.io.ref.block = start_block;
|
j->d.io.ref.block = start_block;
|
||||||
j->buffer = bl.buf + (j->d.io.offset & (block_size()-1));
|
j->buffer = bl.buf + (j->d.io.offset & (block_size()-1));
|
||||||
++m_send_buffer_blocks;
|
++m_send_buffer_blocks;
|
||||||
#if TORRENT_USE_ASSERTS
|
|
||||||
++bl.reading_count;
|
|
||||||
#endif
|
|
||||||
return j->d.io.buffer_size;
|
return j->d.io.buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1703,7 +1710,6 @@ int block_cache::copy_from_piece(cached_piece_entry* pe, disk_io_job* j, bool ex
|
||||||
std::memcpy(j->buffer + buffer_offset
|
std::memcpy(j->buffer + buffer_offset
|
||||||
, pe->blocks[block].buf + block_offset
|
, pe->blocks[block].buf + block_offset
|
||||||
, to_copy);
|
, to_copy);
|
||||||
++pe->blocks[block].hitcount;
|
|
||||||
size -= to_copy;
|
size -= to_copy;
|
||||||
block_offset = 0;
|
block_offset = 0;
|
||||||
buffer_offset += to_copy;
|
buffer_offset += to_copy;
|
||||||
|
|
Loading…
Reference in New Issue