makes all tracker requests 'stopped' when aborting
[libtorrent.git] / include / libtorrent / disk_io_thread.hpp
blob92289674132c0373924c8a53c2fdb1556d8506b6
1 /*
3 Copyright (c) 2007, Arvid Norberg
4 All rights reserved.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the distribution.
15 * Neither the name of the author nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
33 #ifndef TORRENT_DISK_IO_THREAD
34 #define TORRENT_DISK_IO_THREAD
36 #ifdef TORRENT_DISK_STATS
37 #include <fstream>
38 #endif
40 #include "libtorrent/storage.hpp"
41 #include <boost/thread/thread.hpp>
42 #include <boost/function.hpp>
43 #include <boost/thread/mutex.hpp>
44 #include <boost/bind.hpp>
45 #include <boost/noncopyable.hpp>
46 #include <boost/shared_array.hpp>
47 #include <list>
48 #include "libtorrent/config.hpp"
49 #ifndef TORRENT_DISABLE_POOL_ALLOCATOR
50 #include <boost/pool/pool.hpp>
51 #endif
53 namespace libtorrent
56 struct cached_piece_info
58 int piece;
59 std::vector<bool> blocks;
60 ptime last_use;
61 enum kind_t { read_cache = 0, write_cache = 1 };
62 kind_t kind;
65 struct disk_io_job
67 disk_io_job()
68 : action(read)
69 , buffer(0)
70 , buffer_size(0)
71 , piece(0)
72 , offset(0)
73 , priority(0)
76 enum action_t
78 read
79 , write
80 , hash
81 , move_storage
82 , release_files
83 , delete_files
84 , check_fastresume
85 , check_files
86 , save_resume_data
87 , rename_file
88 , abort_thread
89 , clear_read_cache
92 action_t action;
94 char* buffer;
95 int buffer_size;
96 boost::intrusive_ptr<piece_manager> storage;
97 // arguments used for read and write
98 int piece, offset;
99 // used for move_storage and rename_file. On errors, this is set
100 // to the error message
101 std::string str;
103 // on error, this is set to the path of the
104 // file the disk operation failed on
105 std::string error_file;
107 // priority decides whether or not this
108 // job will skip entries in the queue or
109 // not. It always skips in front of entries
110 // with lower priority
111 int priority;
113 boost::shared_ptr<entry> resume_data;
115 // the error code from the file operation
116 error_code error;
118 // this is called when operation completes
119 boost::function<void(int, disk_io_job const&)> callback;
122 struct cache_status
124 cache_status()
125 : blocks_written(0)
126 , writes(0)
127 , blocks_read(0)
128 , blocks_read_hit(0)
129 , reads(0)
130 , cache_size(0)
131 , read_cache_size(0)
134 // the number of 16kB blocks written
135 size_type blocks_written;
136 // the number of write operations used
137 size_type writes;
138 // (blocks_written - writes) / blocks_written represents the
139 // "cache hit" ratio in the write cache
140 // the number of blocks read
142 // the number of blocks passed back to the bittorrent engine
143 size_type blocks_read;
144 // the number of blocks that was just copied from the read cache
145 size_type blocks_read_hit;
146 // the number of read operations used
147 size_type reads;
149 // the number of blocks in the cache (both read and write)
150 int cache_size;
152 // the number of blocks in the cache used for read cache
153 int read_cache_size;
156 // this is a singleton consisting of the thread and a queue
157 // of disk io jobs
158 struct disk_io_thread : boost::noncopyable
160 disk_io_thread(io_service& ios, int block_size = 16 * 1024);
161 ~disk_io_thread();
163 #ifdef TORRENT_STATS
164 int disk_allocations() const
165 { return m_allocations; }
166 #endif
168 void join();
170 // aborts read operations
171 void stop(boost::intrusive_ptr<piece_manager> s);
172 void add_job(disk_io_job const& j
173 , boost::function<void(int, disk_io_job const&)> const& f
174 = boost::function<void(int, disk_io_job const&)>());
176 // keep track of the number of bytes in the job queue
177 // at any given time. i.e. the sum of all buffer_size.
178 // this is used to slow down the download global download
179 // speed when the queue buffer size is too big.
180 size_type queue_buffer_size() const
181 { return m_queue_buffer_size; }
183 void get_cache_info(sha1_hash const& ih
184 , std::vector<cached_piece_info>& ret) const;
186 cache_status status() const;
187 void set_cache_size(int s);
188 void set_cache_expiry(int ex);
190 void operator()();
192 #ifndef NDEBUG
193 bool is_disk_buffer(char* buffer) const;
194 #endif
196 char* allocate_buffer();
197 void free_buffer(char* buf);
199 #ifndef NDEBUG
200 void check_invariant() const;
201 #endif
203 private:
205 struct cached_piece_entry
207 int piece;
208 // storage this piece belongs to
209 boost::intrusive_ptr<piece_manager> storage;
210 // the last time a block was writting to this piece
211 ptime last_use;
212 // the number of blocks in the cache for this piece
213 int num_blocks;
214 // the pointers to the block data
215 boost::shared_array<char*> blocks;
218 typedef boost::recursive_mutex mutex_t;
219 typedef std::list<cached_piece_entry> cache_t;
221 bool test_error(disk_io_job& j);
223 // cache operations
224 cache_t::iterator find_cached_piece(
225 cache_t& cache, disk_io_job const& j
226 , mutex_t::scoped_lock& l);
228 // write cache operations
229 void flush_oldest_piece(mutex_t::scoped_lock& l);
230 void flush_expired_pieces();
231 void flush_and_remove(cache_t::iterator i, mutex_t::scoped_lock& l);
232 void flush(cache_t::iterator i, mutex_t::scoped_lock& l);
233 void cache_block(disk_io_job& j, mutex_t::scoped_lock& l);
235 // read cache operations
236 bool clear_oldest_read_piece(cache_t::iterator ignore
237 , mutex_t::scoped_lock& l);
238 int read_into_piece(cached_piece_entry& p, int start_block, mutex_t::scoped_lock& l);
239 int cache_read_block(disk_io_job const& j, mutex_t::scoped_lock& l);
240 void free_piece(cached_piece_entry& p, mutex_t::scoped_lock& l);
241 bool make_room(int num_blocks
242 , cache_t::iterator ignore
243 , mutex_t::scoped_lock& l);
244 int try_read_from_cache(disk_io_job const& j);
246 // this mutex only protects m_jobs, m_queue_buffer_size
247 // and m_abort
248 mutable mutex_t m_queue_mutex;
249 boost::condition m_signal;
250 bool m_abort;
251 std::list<disk_io_job> m_jobs;
252 size_type m_queue_buffer_size;
254 // this protects the piece cache and related members
255 mutable mutex_t m_piece_mutex;
256 // write cache
257 cache_t m_pieces;
259 // read cache
260 cache_t m_read_pieces;
262 // total number of blocks in use by both the read
263 // and the write cache. This is not supposed to
264 // exceed m_cache_size
265 cache_status m_cache_stats;
266 int m_num_cached_blocks;
268 // in (16kB) blocks
269 int m_cache_size;
271 // expiration time of cache entries in seconds
272 int m_cache_expiry;
274 // if set to true, each piece flush will allocate
275 // one piece worth of temporary memory on the heap
276 // and copy the block data into it, and then perform
277 // a single write operation from that buffer.
278 // if memory is constrained, that temporary buffer
279 // might is avoided by setting this to false.
280 // in case the allocation fails, the piece flush
281 // falls back to writing each block separately.
282 bool m_coalesce_writes;
283 bool m_coalesce_reads;
284 bool m_use_read_cache;
286 // this only protects the pool allocator
287 mutable mutex_t m_pool_mutex;
288 #ifndef TORRENT_DISABLE_POOL_ALLOCATOR
289 // memory pool for read and write operations
290 // and disk cache
291 boost::pool<> m_pool;
292 #endif
294 // number of bytes per block. The BitTorrent
295 // protocol defines the block size to 16 KiB.
296 int m_block_size;
298 #ifdef TORRENT_DISK_STATS
299 std::ofstream m_log;
300 #endif
301 #ifdef TORRENT_STATS
302 int m_allocations;
303 #endif
305 size_type m_writes;
306 size_type m_blocks_written;
308 io_service& m_ios;
310 // thread for performing blocking disk io operations
311 boost::thread m_disk_io_thread;
316 #endif