added disk cache for write operations

This commit is contained in:
Arvid Norberg 2008-02-08 10:22:05 +00:00
parent 196f9c3544
commit 8cf0510144
18 changed files with 645 additions and 166 deletions

View File

@ -1,3 +1,4 @@
* Disk cache support.
* New, more memory efficient, piece picker with sequential download
support (instead of the more complicated sequential download threshold).
* Auto Upload slots. Automtically opens up more slots if

View File

@ -39,162 +39,164 @@
<li><a class="reference" href="#set-max-half-open-connections-max-half-open-connections" id="id30" name="id30">set_max_half_open_connections() max_half_open_connections()</a></li>
<li><a class="reference" href="#set-ip-filter" id="id31" name="id31">set_ip_filter()</a></li>
<li><a class="reference" href="#status" id="id32" name="id32">status()</a></li>
<li><a class="reference" href="#is-listening-listen-port-listen-on" id="id33" name="id33">is_listening() listen_port() listen_on()</a></li>
<li><a class="reference" href="#pop-alert-set-severity-level" id="id34" name="id34">pop_alert() set_severity_level()</a></li>
<li><a class="reference" href="#add-extension" id="id35" name="id35">add_extension()</a></li>
<li><a class="reference" href="#set-settings-set-pe-settings" id="id36" name="id36">set_settings() set_pe_settings()</a></li>
<li><a class="reference" href="#set-peer-proxy-set-web-seed-proxy-set-tracker-proxy-set-dht-proxy" id="id37" name="id37">set_peer_proxy() set_web_seed_proxy() set_tracker_proxy() set_dht_proxy()</a></li>
<li><a class="reference" href="#peer-proxy-web-seed-proxy-tracker-proxy-dht-proxy" id="id38" name="id38">peer_proxy() web_seed_proxy() tracker_proxy() dht_proxy()</a></li>
<li><a class="reference" href="#start-dht-stop-dht-set-dht-settings-dht-state" id="id39" name="id39">start_dht() stop_dht() set_dht_settings() dht_state()</a></li>
<li><a class="reference" href="#add-dht-node-add-dht-router" id="id40" name="id40">add_dht_node() add_dht_router()</a></li>
<li><a class="reference" href="#get-cache-status" id="id33" name="id33">get_cache_status()</a></li>
<li><a class="reference" href="#get-cache-info" id="id34" name="id34">get_cache_info()</a></li>
<li><a class="reference" href="#is-listening-listen-port-listen-on" id="id35" name="id35">is_listening() listen_port() listen_on()</a></li>
<li><a class="reference" href="#pop-alert-set-severity-level" id="id36" name="id36">pop_alert() set_severity_level()</a></li>
<li><a class="reference" href="#add-extension" id="id37" name="id37">add_extension()</a></li>
<li><a class="reference" href="#set-settings-set-pe-settings" id="id38" name="id38">set_settings() set_pe_settings()</a></li>
<li><a class="reference" href="#set-peer-proxy-set-web-seed-proxy-set-tracker-proxy-set-dht-proxy" id="id39" name="id39">set_peer_proxy() set_web_seed_proxy() set_tracker_proxy() set_dht_proxy()</a></li>
<li><a class="reference" href="#peer-proxy-web-seed-proxy-tracker-proxy-dht-proxy" id="id40" name="id40">peer_proxy() web_seed_proxy() tracker_proxy() dht_proxy()</a></li>
<li><a class="reference" href="#start-dht-stop-dht-set-dht-settings-dht-state" id="id41" name="id41">start_dht() stop_dht() set_dht_settings() dht_state()</a></li>
<li><a class="reference" href="#add-dht-node-add-dht-router" id="id42" name="id42">add_dht_node() add_dht_router()</a></li>
</ul>
</li>
<li><a class="reference" href="#entry" id="id41" name="id41">entry</a><ul>
<li><a class="reference" href="#integer-string-list-dict-type" id="id42" name="id42">integer() string() list() dict() type()</a></li>
<li><a class="reference" href="#operator" id="id43" name="id43">operator[]</a></li>
<li><a class="reference" href="#find-key" id="id44" name="id44">find_key()</a></li>
<li><a class="reference" href="#entry" id="id43" name="id43">entry</a><ul>
<li><a class="reference" href="#integer-string-list-dict-type" id="id44" name="id44">integer() string() list() dict() type()</a></li>
<li><a class="reference" href="#operator" id="id45" name="id45">operator[]</a></li>
<li><a class="reference" href="#find-key" id="id46" name="id46">find_key()</a></li>
</ul>
</li>
<li><a class="reference" href="#torrent-info" id="id45" name="id45">torrent_info</a><ul>
<li><a class="reference" href="#id3" id="id46" name="id46">torrent_info()</a></li>
<li><a class="reference" href="#set-comment-set-piece-size-set-creator-set-hash-add-tracker-add-file" id="id47" name="id47">set_comment() set_piece_size() set_creator() set_hash() add_tracker() add_file()</a></li>
<li><a class="reference" href="#create-torrent" id="id48" name="id48">create_torrent()</a></li>
<li><a class="reference" href="#remap-files" id="id49" name="id49">remap_files()</a></li>
<li><a class="reference" href="#begin-files-end-files-rbegin-files-rend-files" id="id50" name="id50">begin_files() end_files() rbegin_files() rend_files()</a></li>
<li><a class="reference" href="#num-files-file-at" id="id51" name="id51">num_files() file_at()</a></li>
<li><a class="reference" href="#map-block" id="id52" name="id52">map_block()</a></li>
<li><a class="reference" href="#map-file" id="id53" name="id53">map_file()</a></li>
<li><a class="reference" href="#url-seeds-add-url-seed" id="id54" name="id54">url_seeds() add_url_seed()</a></li>
<li><a class="reference" href="#print" id="id55" name="id55">print()</a></li>
<li><a class="reference" href="#trackers" id="id56" name="id56">trackers()</a></li>
<li><a class="reference" href="#total-size-piece-length-piece-size-num-pieces" id="id57" name="id57">total_size() piece_length() piece_size() num_pieces()</a></li>
<li><a class="reference" href="#hash-for-piece-info-hash" id="id58" name="id58">hash_for_piece() info_hash()</a></li>
<li><a class="reference" href="#name-comment-creation-date-creator" id="id59" name="id59">name() comment() creation_date() creator()</a></li>
<li><a class="reference" href="#priv-set-priv" id="id60" name="id60">priv() set_priv()</a></li>
<li><a class="reference" href="#nodes" id="id61" name="id61">nodes()</a></li>
<li><a class="reference" href="#add-node" id="id62" name="id62">add_node()</a></li>
<li><a class="reference" href="#torrent-info" id="id47" name="id47">torrent_info</a><ul>
<li><a class="reference" href="#id3" id="id48" name="id48">torrent_info()</a></li>
<li><a class="reference" href="#set-comment-set-piece-size-set-creator-set-hash-add-tracker-add-file" id="id49" name="id49">set_comment() set_piece_size() set_creator() set_hash() add_tracker() add_file()</a></li>
<li><a class="reference" href="#create-torrent" id="id50" name="id50">create_torrent()</a></li>
<li><a class="reference" href="#remap-files" id="id51" name="id51">remap_files()</a></li>
<li><a class="reference" href="#begin-files-end-files-rbegin-files-rend-files" id="id52" name="id52">begin_files() end_files() rbegin_files() rend_files()</a></li>
<li><a class="reference" href="#num-files-file-at" id="id53" name="id53">num_files() file_at()</a></li>
<li><a class="reference" href="#map-block" id="id54" name="id54">map_block()</a></li>
<li><a class="reference" href="#map-file" id="id55" name="id55">map_file()</a></li>
<li><a class="reference" href="#url-seeds-add-url-seed" id="id56" name="id56">url_seeds() add_url_seed()</a></li>
<li><a class="reference" href="#print" id="id57" name="id57">print()</a></li>
<li><a class="reference" href="#trackers" id="id58" name="id58">trackers()</a></li>
<li><a class="reference" href="#total-size-piece-length-piece-size-num-pieces" id="id59" name="id59">total_size() piece_length() piece_size() num_pieces()</a></li>
<li><a class="reference" href="#hash-for-piece-info-hash" id="id60" name="id60">hash_for_piece() info_hash()</a></li>
<li><a class="reference" href="#name-comment-creation-date-creator" id="id61" name="id61">name() comment() creation_date() creator()</a></li>
<li><a class="reference" href="#priv-set-priv" id="id62" name="id62">priv() set_priv()</a></li>
<li><a class="reference" href="#nodes" id="id63" name="id63">nodes()</a></li>
<li><a class="reference" href="#add-node" id="id64" name="id64">add_node()</a></li>
</ul>
</li>
<li><a class="reference" href="#torrent-handle" id="id63" name="id63">torrent_handle</a><ul>
<li><a class="reference" href="#piece-priority-prioritize-pieces-piece-priorities-prioritize-files" id="id64" name="id64">piece_priority() prioritize_pieces() piece_priorities() prioritize_files()</a></li>
<li><a class="reference" href="#file-progress" id="id65" name="id65">file_progress()</a></li>
<li><a class="reference" href="#save-path" id="id66" name="id66">save_path()</a></li>
<li><a class="reference" href="#move-storage" id="id67" name="id67">move_storage()</a></li>
<li><a class="reference" href="#force-reannounce" id="id68" name="id68">force_reannounce()</a></li>
<li><a class="reference" href="#scrape-tracker" id="id69" name="id69">scrape_tracker()</a></li>
<li><a class="reference" href="#connect-peer" id="id70" name="id70">connect_peer()</a></li>
<li><a class="reference" href="#name" id="id71" name="id71">name()</a></li>
<li><a class="reference" href="#set-ratio" id="id72" name="id72">set_ratio()</a></li>
<li><a class="reference" href="#set-upload-limit-set-download-limit-upload-limit-download-limit" id="id73" name="id73">set_upload_limit() set_download_limit() upload_limit() download_limit()</a></li>
<li><a class="reference" href="#set-sequential-download" id="id74" name="id74">set_sequential_download()</a></li>
<li><a class="reference" href="#set-peer-upload-limit-set-peer-download-limit" id="id75" name="id75">set_peer_upload_limit() set_peer_download_limit()</a></li>
<li><a class="reference" href="#pause-resume-is-paused" id="id76" name="id76">pause() resume() is_paused()</a></li>
<li><a class="reference" href="#resolve-countries" id="id77" name="id77">resolve_countries()</a></li>
<li><a class="reference" href="#is-seed" id="id78" name="id78">is_seed()</a></li>
<li><a class="reference" href="#has-metadata" id="id79" name="id79">has_metadata()</a></li>
<li><a class="reference" href="#set-tracker-login" id="id80" name="id80">set_tracker_login()</a></li>
<li><a class="reference" href="#trackers-replace-trackers" id="id81" name="id81">trackers() replace_trackers()</a></li>
<li><a class="reference" href="#add-url-seed-remove-url-seed-url-seeds" id="id82" name="id82">add_url_seed() remove_url_seed() url_seeds()</a></li>
<li><a class="reference" href="#use-interface" id="id83" name="id83">use_interface()</a></li>
<li><a class="reference" href="#info-hash" id="id84" name="id84">info_hash()</a></li>
<li><a class="reference" href="#id5" id="id85" name="id85">set_max_uploads() set_max_connections()</a></li>
<li><a class="reference" href="#write-resume-data" id="id86" name="id86">write_resume_data()</a></li>
<li><a class="reference" href="#id6" id="id87" name="id87">status()</a></li>
<li><a class="reference" href="#get-download-queue" id="id88" name="id88">get_download_queue()</a></li>
<li><a class="reference" href="#get-peer-info" id="id89" name="id89">get_peer_info()</a></li>
<li><a class="reference" href="#get-torrent-info" id="id90" name="id90">get_torrent_info()</a></li>
<li><a class="reference" href="#is-valid" id="id91" name="id91">is_valid()</a></li>
<li><a class="reference" href="#torrent-handle" id="id65" name="id65">torrent_handle</a><ul>
<li><a class="reference" href="#piece-priority-prioritize-pieces-piece-priorities-prioritize-files" id="id66" name="id66">piece_priority() prioritize_pieces() piece_priorities() prioritize_files()</a></li>
<li><a class="reference" href="#file-progress" id="id67" name="id67">file_progress()</a></li>
<li><a class="reference" href="#save-path" id="id68" name="id68">save_path()</a></li>
<li><a class="reference" href="#move-storage" id="id69" name="id69">move_storage()</a></li>
<li><a class="reference" href="#force-reannounce" id="id70" name="id70">force_reannounce()</a></li>
<li><a class="reference" href="#scrape-tracker" id="id71" name="id71">scrape_tracker()</a></li>
<li><a class="reference" href="#connect-peer" id="id72" name="id72">connect_peer()</a></li>
<li><a class="reference" href="#name" id="id73" name="id73">name()</a></li>
<li><a class="reference" href="#set-ratio" id="id74" name="id74">set_ratio()</a></li>
<li><a class="reference" href="#set-upload-limit-set-download-limit-upload-limit-download-limit" id="id75" name="id75">set_upload_limit() set_download_limit() upload_limit() download_limit()</a></li>
<li><a class="reference" href="#set-sequential-download" id="id76" name="id76">set_sequential_download()</a></li>
<li><a class="reference" href="#set-peer-upload-limit-set-peer-download-limit" id="id77" name="id77">set_peer_upload_limit() set_peer_download_limit()</a></li>
<li><a class="reference" href="#pause-resume-is-paused" id="id78" name="id78">pause() resume() is_paused()</a></li>
<li><a class="reference" href="#resolve-countries" id="id79" name="id79">resolve_countries()</a></li>
<li><a class="reference" href="#is-seed" id="id80" name="id80">is_seed()</a></li>
<li><a class="reference" href="#has-metadata" id="id81" name="id81">has_metadata()</a></li>
<li><a class="reference" href="#set-tracker-login" id="id82" name="id82">set_tracker_login()</a></li>
<li><a class="reference" href="#trackers-replace-trackers" id="id83" name="id83">trackers() replace_trackers()</a></li>
<li><a class="reference" href="#add-url-seed-remove-url-seed-url-seeds" id="id84" name="id84">add_url_seed() remove_url_seed() url_seeds()</a></li>
<li><a class="reference" href="#use-interface" id="id85" name="id85">use_interface()</a></li>
<li><a class="reference" href="#info-hash" id="id86" name="id86">info_hash()</a></li>
<li><a class="reference" href="#id5" id="id87" name="id87">set_max_uploads() set_max_connections()</a></li>
<li><a class="reference" href="#write-resume-data" id="id88" name="id88">write_resume_data()</a></li>
<li><a class="reference" href="#id6" id="id89" name="id89">status()</a></li>
<li><a class="reference" href="#get-download-queue" id="id90" name="id90">get_download_queue()</a></li>
<li><a class="reference" href="#get-peer-info" id="id91" name="id91">get_peer_info()</a></li>
<li><a class="reference" href="#get-torrent-info" id="id92" name="id92">get_torrent_info()</a></li>
<li><a class="reference" href="#is-valid" id="id93" name="id93">is_valid()</a></li>
</ul>
</li>
<li><a class="reference" href="#torrent-status" id="id92" name="id92">torrent_status</a></li>
<li><a class="reference" href="#peer-info" id="id93" name="id93">peer_info</a></li>
<li><a class="reference" href="#session-settings" id="id94" name="id94">session_settings</a></li>
<li><a class="reference" href="#pe-settings" id="id95" name="id95">pe_settings</a></li>
<li><a class="reference" href="#proxy-settings" id="id96" name="id96">proxy_settings</a></li>
<li><a class="reference" href="#ip-filter" id="id97" name="id97">ip_filter</a><ul>
<li><a class="reference" href="#id9" id="id98" name="id98">ip_filter()</a></li>
<li><a class="reference" href="#add-rule" id="id99" name="id99">add_rule()</a></li>
<li><a class="reference" href="#access" id="id100" name="id100">access()</a></li>
<li><a class="reference" href="#export-filter" id="id101" name="id101">export_filter()</a></li>
<li><a class="reference" href="#torrent-status" id="id94" name="id94">torrent_status</a></li>
<li><a class="reference" href="#peer-info" id="id95" name="id95">peer_info</a></li>
<li><a class="reference" href="#session-settings" id="id96" name="id96">session_settings</a></li>
<li><a class="reference" href="#pe-settings" id="id97" name="id97">pe_settings</a></li>
<li><a class="reference" href="#proxy-settings" id="id98" name="id98">proxy_settings</a></li>
<li><a class="reference" href="#ip-filter" id="id99" name="id99">ip_filter</a><ul>
<li><a class="reference" href="#id9" id="id100" name="id100">ip_filter()</a></li>
<li><a class="reference" href="#add-rule" id="id101" name="id101">add_rule()</a></li>
<li><a class="reference" href="#access" id="id102" name="id102">access()</a></li>
<li><a class="reference" href="#export-filter" id="id103" name="id103">export_filter()</a></li>
</ul>
</li>
<li><a class="reference" href="#big-number" id="id102" name="id102">big_number</a></li>
<li><a class="reference" href="#hasher" id="id103" name="id103">hasher</a></li>
<li><a class="reference" href="#fingerprint" id="id104" name="id104">fingerprint</a></li>
<li><a class="reference" href="#free-functions" id="id105" name="id105">free functions</a><ul>
<li><a class="reference" href="#identify-client" id="id106" name="id106">identify_client()</a></li>
<li><a class="reference" href="#client-fingerprint" id="id107" name="id107">client_fingerprint()</a></li>
<li><a class="reference" href="#bdecode-bencode" id="id108" name="id108">bdecode() bencode()</a></li>
<li><a class="reference" href="#supports-sparse-files" id="id109" name="id109">supports_sparse_files()</a></li>
<li><a class="reference" href="#big-number" id="id104" name="id104">big_number</a></li>
<li><a class="reference" href="#hasher" id="id105" name="id105">hasher</a></li>
<li><a class="reference" href="#fingerprint" id="id106" name="id106">fingerprint</a></li>
<li><a class="reference" href="#free-functions" id="id107" name="id107">free functions</a><ul>
<li><a class="reference" href="#identify-client" id="id108" name="id108">identify_client()</a></li>
<li><a class="reference" href="#client-fingerprint" id="id109" name="id109">client_fingerprint()</a></li>
<li><a class="reference" href="#bdecode-bencode" id="id110" name="id110">bdecode() bencode()</a></li>
<li><a class="reference" href="#supports-sparse-files" id="id111" name="id111">supports_sparse_files()</a></li>
</ul>
</li>
<li><a class="reference" href="#alerts" id="id110" name="id110">alerts</a><ul>
<li><a class="reference" href="#listen-failed-alert" id="id111" name="id111">listen_failed_alert</a></li>
<li><a class="reference" href="#portmap-error-alert" id="id112" name="id112">portmap_error_alert</a></li>
<li><a class="reference" href="#portmap-alert" id="id113" name="id113">portmap_alert</a></li>
<li><a class="reference" href="#file-error-alert" id="id114" name="id114">file_error_alert</a></li>
<li><a class="reference" href="#tracker-announce-alert" id="id115" name="id115">tracker_announce_alert</a></li>
<li><a class="reference" href="#tracker-alert" id="id116" name="id116">tracker_alert</a></li>
<li><a class="reference" href="#tracker-reply-alert" id="id117" name="id117">tracker_reply_alert</a></li>
<li><a class="reference" href="#tracker-warning-alert" id="id118" name="id118">tracker_warning_alert</a></li>
<li><a class="reference" href="#scrape-reply-alert" id="id119" name="id119">scrape_reply_alert</a></li>
<li><a class="reference" href="#scrape-failed-alert" id="id120" name="id120">scrape_failed_alert</a></li>
<li><a class="reference" href="#url-seed-alert" id="id121" name="id121">url_seed_alert</a></li>
<li><a class="reference" href="#hash-failed-alert" id="id122" name="id122">hash_failed_alert</a></li>
<li><a class="reference" href="#peer-ban-alert" id="id123" name="id123">peer_ban_alert</a></li>
<li><a class="reference" href="#peer-error-alert" id="id124" name="id124">peer_error_alert</a></li>
<li><a class="reference" href="#invalid-request-alert" id="id125" name="id125">invalid_request_alert</a></li>
<li><a class="reference" href="#torrent-finished-alert" id="id126" name="id126">torrent_finished_alert</a></li>
<li><a class="reference" href="#metadata-failed-alert" id="id127" name="id127">metadata_failed_alert</a></li>
<li><a class="reference" href="#metadata-received-alert" id="id128" name="id128">metadata_received_alert</a></li>
<li><a class="reference" href="#fastresume-rejected-alert" id="id129" name="id129">fastresume_rejected_alert</a></li>
<li><a class="reference" href="#peer-blocked-alert" id="id130" name="id130">peer_blocked_alert</a></li>
<li><a class="reference" href="#storage-moved-alert" id="id131" name="id131">storage_moved_alert</a></li>
<li><a class="reference" href="#torrent-paused-alert" id="id132" name="id132">torrent_paused_alert</a></li>
<li><a class="reference" href="#dispatcher" id="id133" name="id133">dispatcher</a></li>
<li><a class="reference" href="#alerts" id="id112" name="id112">alerts</a><ul>
<li><a class="reference" href="#listen-failed-alert" id="id113" name="id113">listen_failed_alert</a></li>
<li><a class="reference" href="#portmap-error-alert" id="id114" name="id114">portmap_error_alert</a></li>
<li><a class="reference" href="#portmap-alert" id="id115" name="id115">portmap_alert</a></li>
<li><a class="reference" href="#file-error-alert" id="id116" name="id116">file_error_alert</a></li>
<li><a class="reference" href="#tracker-announce-alert" id="id117" name="id117">tracker_announce_alert</a></li>
<li><a class="reference" href="#tracker-alert" id="id118" name="id118">tracker_alert</a></li>
<li><a class="reference" href="#tracker-reply-alert" id="id119" name="id119">tracker_reply_alert</a></li>
<li><a class="reference" href="#tracker-warning-alert" id="id120" name="id120">tracker_warning_alert</a></li>
<li><a class="reference" href="#scrape-reply-alert" id="id121" name="id121">scrape_reply_alert</a></li>
<li><a class="reference" href="#scrape-failed-alert" id="id122" name="id122">scrape_failed_alert</a></li>
<li><a class="reference" href="#url-seed-alert" id="id123" name="id123">url_seed_alert</a></li>
<li><a class="reference" href="#hash-failed-alert" id="id124" name="id124">hash_failed_alert</a></li>
<li><a class="reference" href="#peer-ban-alert" id="id125" name="id125">peer_ban_alert</a></li>
<li><a class="reference" href="#peer-error-alert" id="id126" name="id126">peer_error_alert</a></li>
<li><a class="reference" href="#invalid-request-alert" id="id127" name="id127">invalid_request_alert</a></li>
<li><a class="reference" href="#torrent-finished-alert" id="id128" name="id128">torrent_finished_alert</a></li>
<li><a class="reference" href="#metadata-failed-alert" id="id129" name="id129">metadata_failed_alert</a></li>
<li><a class="reference" href="#metadata-received-alert" id="id130" name="id130">metadata_received_alert</a></li>
<li><a class="reference" href="#fastresume-rejected-alert" id="id131" name="id131">fastresume_rejected_alert</a></li>
<li><a class="reference" href="#peer-blocked-alert" id="id132" name="id132">peer_blocked_alert</a></li>
<li><a class="reference" href="#storage-moved-alert" id="id133" name="id133">storage_moved_alert</a></li>
<li><a class="reference" href="#torrent-paused-alert" id="id134" name="id134">torrent_paused_alert</a></li>
<li><a class="reference" href="#dispatcher" id="id135" name="id135">dispatcher</a></li>
</ul>
</li>
<li><a class="reference" href="#exceptions" id="id134" name="id134">exceptions</a><ul>
<li><a class="reference" href="#invalid-handle" id="id135" name="id135">invalid_handle</a></li>
<li><a class="reference" href="#duplicate-torrent" id="id136" name="id136">duplicate_torrent</a></li>
<li><a class="reference" href="#invalid-encoding" id="id137" name="id137">invalid_encoding</a></li>
<li><a class="reference" href="#type-error" id="id138" name="id138">type_error</a></li>
<li><a class="reference" href="#invalid-torrent-file" id="id139" name="id139">invalid_torrent_file</a></li>
<li><a class="reference" href="#exceptions" id="id136" name="id136">exceptions</a><ul>
<li><a class="reference" href="#invalid-handle" id="id137" name="id137">invalid_handle</a></li>
<li><a class="reference" href="#duplicate-torrent" id="id138" name="id138">duplicate_torrent</a></li>
<li><a class="reference" href="#invalid-encoding" id="id139" name="id139">invalid_encoding</a></li>
<li><a class="reference" href="#type-error" id="id140" name="id140">type_error</a></li>
<li><a class="reference" href="#invalid-torrent-file" id="id141" name="id141">invalid_torrent_file</a></li>
</ul>
</li>
<li><a class="reference" href="#storage-interface" id="id140" name="id140">storage_interface</a><ul>
<li><a class="reference" href="#initialize" id="id141" name="id141">initialize()</a></li>
<li><a class="reference" href="#read" id="id142" name="id142">read()</a></li>
<li><a class="reference" href="#write" id="id143" name="id143">write()</a></li>
<li><a class="reference" href="#id11" id="id144" name="id144">move_storage()</a></li>
<li><a class="reference" href="#verify-resume-data" id="id145" name="id145">verify_resume_data()</a></li>
<li><a class="reference" href="#id12" id="id146" name="id146">write_resume_data( )</a></li>
<li><a class="reference" href="#move-slot" id="id147" name="id147">move_slot()</a></li>
<li><a class="reference" href="#swap-slots" id="id148" name="id148">swap_slots()</a></li>
<li><a class="reference" href="#swap-slots3" id="id149" name="id149">swap_slots3()</a></li>
<li><a class="reference" href="#hash-for-slot" id="id150" name="id150">hash_for_slot()</a></li>
<li><a class="reference" href="#release-files" id="id151" name="id151">release_files()</a></li>
<li><a class="reference" href="#delete-files" id="id152" name="id152">delete_files()</a></li>
<li><a class="reference" href="#storage-interface" id="id142" name="id142">storage_interface</a><ul>
<li><a class="reference" href="#initialize" id="id143" name="id143">initialize()</a></li>
<li><a class="reference" href="#read" id="id144" name="id144">read()</a></li>
<li><a class="reference" href="#write" id="id145" name="id145">write()</a></li>
<li><a class="reference" href="#id11" id="id146" name="id146">move_storage()</a></li>
<li><a class="reference" href="#verify-resume-data" id="id147" name="id147">verify_resume_data()</a></li>
<li><a class="reference" href="#id12" id="id148" name="id148">write_resume_data( )</a></li>
<li><a class="reference" href="#move-slot" id="id149" name="id149">move_slot()</a></li>
<li><a class="reference" href="#swap-slots" id="id150" name="id150">swap_slots()</a></li>
<li><a class="reference" href="#swap-slots3" id="id151" name="id151">swap_slots3()</a></li>
<li><a class="reference" href="#hash-for-slot" id="id152" name="id152">hash_for_slot()</a></li>
<li><a class="reference" href="#release-files" id="id153" name="id153">release_files()</a></li>
<li><a class="reference" href="#delete-files" id="id154" name="id154">delete_files()</a></li>
</ul>
</li>
<li><a class="reference" href="#fast-resume" id="id153" name="id153">fast resume</a><ul>
<li><a class="reference" href="#file-format" id="id154" name="id154">file format</a></li>
<li><a class="reference" href="#fast-resume" id="id155" name="id155">fast resume</a><ul>
<li><a class="reference" href="#file-format" id="id156" name="id156">file format</a></li>
</ul>
</li>
<li><a class="reference" href="#threads" id="id155" name="id155">threads</a></li>
<li><a class="reference" href="#storage-allocation" id="id156" name="id156">storage allocation</a><ul>
<li><a class="reference" href="#sparse-allocation" id="id157" name="id157">sparse allocation</a></li>
<li><a class="reference" href="#full-allocation" id="id158" name="id158">full allocation</a></li>
<li><a class="reference" href="#compact-allocation" id="id159" name="id159">compact allocation</a></li>
<li><a class="reference" href="#threads" id="id157" name="id157">threads</a></li>
<li><a class="reference" href="#storage-allocation" id="id158" name="id158">storage allocation</a><ul>
<li><a class="reference" href="#sparse-allocation" id="id159" name="id159">sparse allocation</a></li>
<li><a class="reference" href="#full-allocation" id="id160" name="id160">full allocation</a></li>
<li><a class="reference" href="#compact-allocation" id="id161" name="id161">compact allocation</a></li>
</ul>
</li>
<li><a class="reference" href="#extensions" id="id160" name="id160">extensions</a><ul>
<li><a class="reference" href="#metadata-from-peers" id="id161" name="id161">metadata from peers</a></li>
<li><a class="reference" href="#http-seeding" id="id162" name="id162">HTTP seeding</a></li>
<li><a class="reference" href="#extensions" id="id162" name="id162">extensions</a><ul>
<li><a class="reference" href="#metadata-from-peers" id="id163" name="id163">metadata from peers</a></li>
<li><a class="reference" href="#http-seeding" id="id164" name="id164">HTTP seeding</a></li>
</ul>
</li>
<li><a class="reference" href="#filename-checks" id="id163" name="id163">filename checks</a></li>
<li><a class="reference" href="#acknowledgments" id="id164" name="id164">acknowledgments</a></li>
<li><a class="reference" href="#filename-checks" id="id165" name="id165">filename checks</a></li>
<li><a class="reference" href="#acknowledgments" id="id166" name="id166">acknowledgments</a></li>
</ul>
</div>
<div class="section">
@ -319,6 +321,7 @@ class session: public boost::noncopyable
void set_ip_filter(ip_filter const&amp; f);
session_status status() const;
cache_status get_cache_status() const;
bool is_listening() const;
unsigned short listen_port() const;
@ -644,6 +647,60 @@ becomes unresponsive.</p>
network.</p>
</div>
<div class="section">
<h2><a id="get-cache-status" name="get-cache-status">get_cache_status()</a></h2>
<blockquote>
<pre class="literal-block">
cache_status get_cache_status() const;
</pre>
</blockquote>
<p>Returns status of the disk cache for this session.</p>
<blockquote>
<pre class="literal-block">
struct cache_status
{
size_type blocks_written;
size_type writes;
int write_size;
};
</pre>
</blockquote>
<p><tt class="docutils literal"><span class="pre">blocks_written</span></tt> is the total number of 16 KiB blocks written to disk
since this session was started.</p>
<p><tt class="docutils literal"><span class="pre">writes</span></tt> is the total number of write operations performed since this
session was started.</p>
<p>The ratio (<tt class="docutils literal"><span class="pre">blocks_written</span></tt> - <tt class="docutils literal"><span class="pre">writes</span></tt>) / <tt class="docutils literal"><span class="pre">blocks_written</span></tt> represents
the number of saved write operations per total write operations. i.e. a kind
of cache hit ratio for the write cahe.</p>
<p><tt class="docutils literal"><span class="pre">write_size</span></tt> is the number of 16 KiB blocks currently in the write cache.</p>
</div>
<div class="section">
<h2><a id="get-cache-info" name="get-cache-info">get_cache_info()</a></h2>
<blockquote>
<pre class="literal-block">
void get_cache_info(sha1_hash const&amp; ih
, std::vector&lt;cached_piece_info&gt;&amp; ret) const;
</pre>
</blockquote>
<p><tt class="docutils literal"><span class="pre">get_cache_info()</span></tt> fills out the supplied vector with information for
each piece that is currently in the disk cache for the torrent with the
specified info-hash (<tt class="docutils literal"><span class="pre">ih</span></tt>).</p>
<blockquote>
<pre class="literal-block">
struct cached_piece_info
{
int piece;
std::vector&lt;bool&gt; blocks;
ptime last_write;
};
</pre>
</blockquote>
<p><tt class="docutils literal"><span class="pre">piece</span></tt> is the piece index for this cache entry.</p>
<p><tt class="docutils literal"><span class="pre">blocks</span></tt> has one entry for each block in this piece. <tt class="docutils literal"><span class="pre">true</span></tt> represents
the data for that block being in the disk cache and <tt class="docutils literal"><span class="pre">false</span></tt> means it's not.</p>
<p><tt class="docutils literal"><span class="pre">last_write</span></tt> is the time when a block was last written to this piece. The older
a piece is, the more likely it is to be flushed to disk.</p>
</div>
<div class="section">
<h2><a id="is-listening-listen-port-listen-on" name="is-listening-listen-port-listen-on">is_listening() listen_port() listen_on()</a></h2>
<blockquote>
<pre class="literal-block">
@ -2529,6 +2586,7 @@ struct session_settings
bool upnp_ignore_nonrouters;
int send_buffer_watermark;
bool auto_upload_slots;
int cache_size;
};
</pre>
<p><tt class="docutils literal"><span class="pre">user_agent</span></tt> this is the client identification to the tracker.
@ -2651,6 +2709,8 @@ slot is opened. If the upload rate has been saturated for an extended period
of time, on upload slot is closed. The number of upload slots will never be
less than what has been set by <tt class="docutils literal"><span class="pre">session::set_max_uploads()</span></tt>. To query the
current number of upload slots, see <tt class="docutils literal"><span class="pre">session_status::allowed_upload_slots</span></tt>.</p>
<p><tt class="docutils literal"><span class="pre">cache_size</span></tt> is the disk write cache. It is specified in units of 16 KiB blocks.
It defaults to 128 (= 2 MB).</p>
</div>
<div class="section">
<h1><a id="pe-settings" name="pe-settings">pe_settings</a></h1>

View File

@ -133,6 +133,7 @@ The ``session`` class has the following synopsis::
void set_ip_filter(ip_filter const& f);
session_status status() const;
cache_status get_cache_status() const;
bool is_listening() const;
unsigned short listen_port() const;
@ -490,6 +491,65 @@ becomes unresponsive.
``dht_global_nodes`` is an estimation of the total number of nodes in the DHT
network.
get_cache_status()
------------------
::
cache_status get_cache_status() const;
Returns status of the disk cache for this session.
::
struct cache_status
{
size_type blocks_written;
size_type writes;
int write_size;
};
``blocks_written`` is the total number of 16 KiB blocks written to disk
since this session was started.
``writes`` is the total number of write operations performed since this
session was started.
The ratio (``blocks_written`` - ``writes``) / ``blocks_written`` represents
the number of saved write operations per total write operations. i.e. a kind
of cache hit ratio for the write cahe.
``write_size`` is the number of 16 KiB blocks currently in the write cache.
get_cache_info()
----------------
::
void get_cache_info(sha1_hash const& ih
, std::vector<cached_piece_info>& ret) const;
``get_cache_info()`` fills out the supplied vector with information for
each piece that is currently in the disk cache for the torrent with the
specified info-hash (``ih``).
::
struct cached_piece_info
{
int piece;
std::vector<bool> blocks;
ptime last_write;
};
``piece`` is the piece index for this cache entry.
``blocks`` has one entry for each block in this piece. ``true`` represents
the data for that block being in the disk cache and ``false`` means it's not.
``last_write`` is the time when a block was last written to this piece. The older
a piece is, the more likely it is to be flushed to disk.
is_listening() listen_port() listen_on()
----------------------------------------
@ -2513,6 +2573,7 @@ that will be sent to the tracker. The user-agent is a good way to identify your
bool upnp_ignore_nonrouters;
int send_buffer_watermark;
bool auto_upload_slots;
int cache_size;
};
``user_agent`` this is the client identification to the tracker.
@ -2663,6 +2724,9 @@ of time, on upload slot is closed. The number of upload slots will never be
less than what has been set by ``session::set_max_uploads()``. To query the
current number of upload slots, see ``session_status::allowed_upload_slots``.
``cache_size`` is the disk write cache. It is specified in units of 16 KiB blocks.
It defaults to 128 (= 2 MB).
pe_settings
===========

View File

@ -896,6 +896,7 @@ int main(int ac, char* av[])
std::vector<partial_piece_info> queue;
bool print_peers = false;
bool print_cache = false;
bool print_log = false;
bool print_downloads = false;
bool print_piece_bar = false;
@ -962,6 +963,7 @@ int main(int ac, char* av[])
}
if (c == 'i') print_peers = !print_peers;
if (c == 'c') print_cache = !print_cache;
if (c == 'l') print_log = !print_log;
if (c == 'd') print_downloads = !print_downloads;
if (c == 'f') print_file_progress = !print_file_progress;
@ -1150,9 +1152,18 @@ int main(int ac, char* av[])
h.get_download_queue(queue);
std::sort(queue.begin(), queue.end(), bind(&partial_piece_info::piece_index, _1)
< bind(&partial_piece_info::piece_index, _2));
std::vector<cached_piece_info> pieces;
ses.get_cache_info(h.info_hash(), pieces);
for (std::vector<partial_piece_info>::iterator i = queue.begin();
i != queue.end(); ++i)
{
cached_piece_info* cp = 0;
std::vector<cached_piece_info>::iterator cpi = std::find_if(pieces.begin(), pieces.end()
, bind(&cached_piece_info::piece, _1) == i->piece_index);
if (cpi != pieces.end()) cp = &*cpi;
out << to_string(i->piece_index, 4) << ": [";
for (int j = 0; j < i->blocks_in_piece; ++j)
{
@ -1162,7 +1173,8 @@ int main(int ac, char* av[])
str[0] = (index < 10)?'0' + index:'A' + index - 10;
#ifdef ANSI_TERMINAL_COLORS
if (i->blocks[j].bytes_progress > 0
if (cp && cp->blocks[j]) out << esc("36;7") << str << esc("0");
else if (i->blocks[j].bytes_progress > 0
&& i->blocks[j].state == block_info::requested)
{
if (i->blocks[j].num_peers > 1)
@ -1176,7 +1188,8 @@ int main(int ac, char* av[])
else if (i->blocks[j].state == block_info::requested) out << str;
else out << " ";
#else
if (i->blocks[j].state == block_info::finished) out << "#";
if (cp && cp->blocks[j]) out << "c";
else if (i->blocks[j].state == block_info::finished) out << "#";
else if (i->blocks[j].state == block_info::writing) out << "+";
else if (i->blocks[j].state == block_info::requested) out << str;
else out << " ";
@ -1211,6 +1224,8 @@ int main(int ac, char* av[])
}
cache_status cs = ses.get_cache_status();
out << "==== conns: " << sess_stat.num_peers
<< " down: " << esc("32") << add_suffix(sess_stat.download_rate) << "/s" << esc("0")
<< " (" << esc("32") << add_suffix(sess_stat.total_download) << esc("0") << ") "
@ -1218,7 +1233,10 @@ int main(int ac, char* av[])
<< " (" << esc("31") << add_suffix(sess_stat.total_upload) << esc("0") << ")"
" unchoked: " << sess_stat.num_unchoked << " / " << sess_stat.allowed_upload_slots
<< " bw queues: (" << sess_stat.up_bandwidth_queue
<< " | " << sess_stat.down_bandwidth_queue << ") ====" << std::endl;
<< " | " << sess_stat.down_bandwidth_queue << ") "
" write cache hits: " << ((cs.blocks_written - cs.writes) * 100 / cs.blocks_written) << "% "
" cache size: " << add_suffix(cs.write_size * 16 * 1024)
<< " ====" << std::endl;
if (print_log)
{

View File

@ -399,19 +399,21 @@ namespace libtorrent
// when they are destructed.
file_pool m_files;
// this is where all active sockets are stored.
// the selector can sleep while there's no activity on
// them
io_service m_io_service;
// handles disk io requests asynchronously
// peers have pointers into the disk buffer
// pool, and must be destructed before this
// object. The disk thread relies on the file
// pool object, and must be destructed before
// m_files.
// m_files. The disk io thread posts completion
// events to the io service, and needs to be
// constructed after it.
disk_io_thread m_disk_thread;
// this is where all active sockets are stored.
// the selector can sleep while there's no activity on
// them
io_service m_io_service;
// this is a list of half-open tcp connections
// (only outgoing connections)
// this has to be one of the last

View File

@ -44,11 +44,19 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/bind.hpp>
#include <boost/pool/pool.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_array.hpp>
#include "libtorrent/config.hpp"
namespace libtorrent
{
struct cached_piece_info
{
int piece;
std::vector<bool> blocks;
ptime last_write;
};
struct disk_io_job
{
disk_io_job()
@ -91,11 +99,22 @@ namespace libtorrent
boost::function<void(int, disk_io_job const&)> callback;
};
struct cache_status
{
// the number of 16kB blocks written
size_type blocks_written;
// the number of write operations used
size_type writes;
// (blocks_written - writes) / blocks_written represents the
// "cache hit" ratio in the write cache
int write_size;
};
// this is a singleton consisting of the thread and a queue
// of disk io jobs
struct disk_io_thread : boost::noncopyable
{
disk_io_thread(int block_size = 16 * 1024);
disk_io_thread(asio::io_service& ios, int block_size = 16 * 1024);
~disk_io_thread();
#ifdef TORRENT_STATS
@ -122,6 +141,12 @@ namespace libtorrent
size_type queue_buffer_size() const
{ return m_queue_buffer_size; }
void get_cache_info(sha1_hash const& ih
, std::vector<cached_piece_info>& ret) const;
cache_status status() const;
void set_cache_size(int s);
void operator()();
char* allocate_buffer();
@ -130,13 +155,43 @@ namespace libtorrent
private:
typedef boost::recursive_mutex mutex_t;
struct cached_piece_entry
{
int piece;
// storage this piece belongs to
boost::intrusive_ptr<piece_manager> storage;
// the last time a block was writting to this piece
ptime last_write;
// the number of blocks in the cache for this piece
int num_blocks;
// the pointers to the block data
boost::shared_array<char*> blocks;
};
char* allocate_buffer(mutex_t::scoped_lock& l);
void free_buffer(char* buf, mutex_t::scoped_lock& l);
std::vector<cached_piece_entry>::iterator find_cached_piece(
disk_io_job const& j, mutex_t::scoped_lock& l);
void flush_oldest_piece(mutex_t::scoped_lock& l);
void flush_and_remove(std::vector<cached_piece_entry>::iterator i, mutex_t::scoped_lock& l);
void flush(std::vector<cached_piece_entry>::iterator i, mutex_t::scoped_lock& l);
void cache_block(disk_io_job& j, mutex_t::scoped_lock& l);
mutable mutex_t m_mutex;
boost::condition m_signal;
bool m_abort;
std::deque<disk_io_job> m_jobs;
size_type m_queue_buffer_size;
std::vector<cached_piece_entry> m_pieces;
int m_num_cached_blocks;
// in (16kB) blocks
int m_cache_size;
// memory pool for read and write operations
// and disk cache
boost::pool<> m_pool;
#ifndef NDEBUG
@ -151,6 +206,11 @@ namespace libtorrent
int m_allocations;
#endif
size_type m_writes;
size_type m_blocks_written;
asio::io_service& m_ios;
// thread for performing blocking disk io operations
boost::thread m_disk_io_thread;
};

View File

@ -61,6 +61,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/version.hpp"
#include "libtorrent/fingerprint.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/disk_io_thread.hpp"
#include "libtorrent/storage.hpp"
@ -176,6 +177,10 @@ namespace libtorrent
session_proxy abort() { return session_proxy(m_impl); }
session_status status() const;
cache_status get_cache_status() const;
void get_cache_info(sha1_hash const& ih
, std::vector<cached_piece_info>& ret) const;
#ifndef TORRENT_DISABLE_DHT
void start_dht(entry const& startup_state = entry());

View File

@ -120,6 +120,7 @@ namespace libtorrent
, upnp_ignore_nonrouters(true)
, send_buffer_watermark(80 * 1024)
, auto_upload_slots(true)
, cache_size(128)
{}
// this is the user agent that will be sent to the tracker
@ -317,6 +318,10 @@ namespace libtorrent
// upload slots are never automatically decreased below
// the manual settings, through max_uploads.
bool auto_upload_slots;
// the disk write cache, specified in 16 KiB blocks.
// defaul is 128 (= 2 MB)
int cache_size;
};
#ifndef TORRENT_DISABLE_DHT

View File

@ -191,6 +191,8 @@ namespace libtorrent
~piece_manager();
torrent_info const* info() const { return m_info.get(); }
bool check_fastresume(aux::piece_checker_data& d
, std::vector<bool>& pieces, int& num_pieces, storage_mode_t storage_mode
, std::string& error_msg);

View File

@ -34,22 +34,30 @@ POSSIBILITY OF SUCH DAMAGE.
#include <deque>
#include "libtorrent/disk_io_thread.hpp"
#ifdef _WIN32
#include <malloc.h>
#define alloca(s) _alloca(s)
#endif
#ifdef TORRENT_DISK_STATS
#include "libtorrent/time.hpp"
#endif
namespace libtorrent
{
disk_io_thread::disk_io_thread(int block_size)
disk_io_thread::disk_io_thread(asio::io_service& ios, int block_size)
: m_abort(false)
, m_queue_buffer_size(0)
, m_num_cached_blocks(0)
, m_cache_size(128) // 128 * 16kB = 2MB
, m_pool(block_size)
#ifndef NDEBUG
, m_block_size(block_size)
#endif
, m_writes(0)
, m_blocks_written(0)
, m_ios(ios)
, m_disk_io_thread(boost::ref(*this))
{
#ifdef TORRENT_STATS
@ -100,6 +108,44 @@ namespace libtorrent
m_disk_io_thread.join();
}
void disk_io_thread::get_cache_info(sha1_hash const& ih, std::vector<cached_piece_info>& ret) const
{
mutex_t::scoped_lock l(m_mutex);
ret.clear();
ret.reserve(m_pieces.size());
for (std::vector<cached_piece_entry>::const_iterator i = m_pieces.begin()
, end(m_pieces.end()); i != end; ++i)
{
torrent_info const& ti = *i->storage->info();
if (ti.info_hash() != ih) continue;
cached_piece_info info;
info.piece = i->piece;
info.last_write = i->last_write;
int blocks_in_piece = (ti.piece_size(i->piece) + (16 * 1024) - 1) / (16 * 1024);
info.blocks.resize(blocks_in_piece);
for (int b = 0; b < blocks_in_piece; ++b)
if (i->blocks[b]) info.blocks[b] = true;
ret.push_back(info);
}
}
cache_status disk_io_thread::status() const
{
mutex_t::scoped_lock l(m_mutex);
cache_status st;
st.blocks_written = m_blocks_written;
st.writes = m_writes;
st.write_size = m_num_cached_blocks;
return st;
}
void disk_io_thread::set_cache_size(int s)
{
mutex_t::scoped_lock l(m_mutex);
TORRENT_ASSERT(s >= 0);
m_cache_size = s;
}
// aborts read operations
void disk_io_thread::stop(boost::intrusive_ptr<piece_manager> s)
{
@ -115,7 +161,7 @@ namespace libtorrent
}
if (i->action == disk_io_job::read)
{
i->callback(-1, *i);
if (i->callback) m_ios.post(bind(i->callback, -1, *i));
m_jobs.erase(i++);
continue;
}
@ -150,14 +196,130 @@ namespace libtorrent
return false;
}
}
std::vector<disk_io_thread::cached_piece_entry>::iterator disk_io_thread::find_cached_piece(
disk_io_job const& j, mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
for (std::vector<cached_piece_entry>::iterator i = m_pieces.begin()
, end(m_pieces.end()); i != end; ++i)
{
if (i->storage != j.storage || i->piece != j.piece) continue;
return i;
}
return m_pieces.end();
}
void disk_io_thread::flush_oldest_piece(mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
std::vector<cached_piece_entry>::iterator i = std::min_element(
m_pieces.begin(), m_pieces.end()
, bind(&cached_piece_entry::last_write, _1)
< bind(&cached_piece_entry::last_write, _1));
if (i == m_pieces.end()) return;
flush_and_remove(i, l);
}
void disk_io_thread::flush_and_remove(std::vector<disk_io_thread::cached_piece_entry>::iterator e
, mutex_t::scoped_lock& l)
{
flush(e, l);
m_pieces.erase(e);
}
void disk_io_thread::flush(std::vector<disk_io_thread::cached_piece_entry>::iterator e
, mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
cached_piece_entry& p = *e;
int piece_size = p.storage->info()->piece_size(p.piece);
TORRENT_ASSERT(piece_size > 0);
// char* buf = (char*)alloca(piece_size);
std::vector<char> temp(piece_size);
char* buf = &temp[0];
TORRENT_ASSERT(buf != 0);
int blocks_in_piece = (piece_size + (16 * 1024) - 1) / (16 * 1024);
int buffer_size = 0;
int offset = 0;
for (int i = 0; i <= blocks_in_piece; ++i)
{
if (i == blocks_in_piece || p.blocks[i] == 0)
{
if (buffer_size == 0) continue;
TORRENT_ASSERT(buffer_size <= i * 16 * 1024);
l.unlock();
p.storage->write_impl(buf, p.piece, (std::min)(i * 16 * 1024, piece_size) - buffer_size, buffer_size);
l.lock();
++m_writes;
// std::cerr << " flushing p: " << p.piece << " bytes: " << buffer_size << std::endl;
buffer_size = 0;
offset = 0;
continue;
}
int block_size = (std::min)(piece_size - offset, 16 * 1024);
TORRENT_ASSERT(offset + block_size <= piece_size);
TORRENT_ASSERT(offset + block_size > 0);
std::memcpy(buf + offset, p.blocks[i], block_size);
offset += 16 * 1024;
free_buffer(p.blocks[i], l);
p.blocks[i] = 0;
buffer_size += block_size;
++m_blocks_written;
--m_num_cached_blocks;
}
TORRENT_ASSERT(buffer_size == 0);
// std::cerr << " flushing p: " << p.piece << " cached_blocks: " << m_num_cached_blocks << std::endl;
#ifndef NDEBUG
for (int i = 0; i < blocks_in_piece; ++i)
TORRENT_ASSERT(p.blocks[i] == 0);
#endif
}
void disk_io_thread::cache_block(disk_io_job& j, mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
TORRENT_ASSERT(find_cached_piece(j, l) == m_pieces.end());
cached_piece_entry p;
int piece_size = j.storage->info()->piece_size(j.piece);
int blocks_in_piece = (piece_size + (16 * 1024) - 1) / (16 * 1024);
p.piece = j.piece;
p.storage = j.storage;
p.last_write = time_now();
p.num_blocks = 1;
p.blocks.reset(new char*[blocks_in_piece]);
std::memset(&p.blocks[0], 0, blocks_in_piece * sizeof(char*));
int block = j.offset / (16 * 1024);
// std::cerr << " adding cache entry for p: " << j.piece << " block: " << block << " cached_blocks: " << m_num_cached_blocks << std::endl;
p.blocks[block] = j.buffer;
++m_num_cached_blocks;
m_pieces.push_back(p);
}
void disk_io_thread::add_job(disk_io_job const& j
, boost::function<void(int, disk_io_job const&)> const& f)
{
TORRENT_ASSERT(!j.callback);
TORRENT_ASSERT(j.storage);
TORRENT_ASSERT(j.buffer_size <= 16 * 1024);
mutex_t::scoped_lock l(m_mutex);
#ifndef NDEBUG
if (j.action == disk_io_job::write)
{
std::vector<cached_piece_entry>::iterator p = find_cached_piece(j, l);
if (p != m_pieces.end())
{
int block = j.offset / (16 * 1024);
char const* buffer = p->blocks[block];
TORRENT_ASSERT(buffer == 0);
}
}
#endif
std::deque<disk_io_job>::reverse_iterator i = m_jobs.rbegin();
if (j.action == disk_io_job::read)
{
@ -212,15 +374,27 @@ namespace libtorrent
char* disk_io_thread::allocate_buffer()
{
mutex_t::scoped_lock l(m_mutex);
return allocate_buffer(l);
}
void disk_io_thread::free_buffer(char* buf)
{
mutex_t::scoped_lock l(m_mutex);
free_buffer(buf, l);
}
char* disk_io_thread::allocate_buffer(mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
#ifdef TORRENT_STATS
++m_allocations;
#endif
return (char*)m_pool.ordered_malloc();
}
void disk_io_thread::free_buffer(char* buf)
void disk_io_thread::free_buffer(char* buf, mutex_t::scoped_lock& l)
{
mutex_t::scoped_lock l(m_mutex);
TORRENT_ASSERT(l.locked());
#ifdef TORRENT_STATS
--m_allocations;
#endif
@ -288,27 +462,53 @@ namespace libtorrent
// usleep(300);
break;
case disk_io_job::write:
{
mutex_t::scoped_lock l(m_mutex);
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " write " << j.buffer_size << std::endl;
#endif
std::vector<cached_piece_entry>::iterator p = find_cached_piece(j, l);
int block = j.offset / (16 * 1024);
TORRENT_ASSERT(j.buffer);
TORRENT_ASSERT(j.buffer_size <= m_block_size);
j.storage->write_impl(j.buffer, j.piece, j.offset
, j.buffer_size);
if (p != m_pieces.end())
{
TORRENT_ASSERT(p->blocks[block] == 0);
if (p->blocks[block]) free_buffer(p->blocks[block]);
p->blocks[block] = j.buffer;
++m_num_cached_blocks;
++p->num_blocks;
p->last_write = time_now();
// std::cerr << " adding cache entry for p: " << j.piece
// << " block: " << block
// << " cached_blocks: " << m_num_cached_blocks << std::endl;
}
else
{
cache_block(j, l);
}
free_current_buffer = false;
if (m_num_cached_blocks >= m_cache_size)
flush_oldest_piece(l);
// simulates a slow drive
// usleep(300);
break;
}
case disk_io_job::hash:
{
{
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " hash" << std::endl;
m_log << log_time() << " hash" << std::endl;
#endif
sha1_hash h = j.storage->hash_for_piece_impl(j.piece);
j.str.resize(20);
std::memcpy(&j.str[0], &h[0], 20);
}
mutex_t::scoped_lock l(m_mutex);
std::vector<cached_piece_entry>::iterator i = find_cached_piece(j, l);
if (i != m_pieces.end()) flush_and_remove(i, l);
l.unlock();
sha1_hash h = j.storage->hash_for_piece_impl(j.piece);
j.str.resize(20);
std::memcpy(&j.str[0], &h[0], 20);
break;
}
case disk_io_job::move_storage:
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " move" << std::endl;
@ -317,17 +517,50 @@ namespace libtorrent
j.str = j.storage->save_path().string();
break;
case disk_io_job::release_files:
{
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " release" << std::endl;
#endif
mutex_t::scoped_lock l(m_mutex);
std::vector<cached_piece_entry>::iterator i = std::remove_if(
m_pieces.begin(), m_pieces.end(), bind(&cached_piece_entry::storage, _1) == j.storage);
for (std::vector<cached_piece_entry>::iterator k = i; k != m_pieces.end(); ++k)
flush(k, l);
m_pieces.erase(i, m_pieces.end());
m_pool.release_memory();
l.unlock();
j.storage->release_files_impl();
break;
}
case disk_io_job::delete_files:
{
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " delete" << std::endl;
#endif
mutex_t::scoped_lock l(m_mutex);
std::vector<cached_piece_entry>::iterator i = std::remove_if(
m_pieces.begin(), m_pieces.end(), bind(&cached_piece_entry::storage, _1) == j.storage);
for (std::vector<cached_piece_entry>::iterator k = i; k != m_pieces.end(); ++k)
{
torrent_info const& ti = *k->storage->info();
int blocks_in_piece = (ti.piece_size(k->piece) + (16 * 1024) - 1) / (16 * 1024);
for (int j = 0; j < blocks_in_piece; ++j)
{
if (k->blocks[j] == 0) continue;
free_buffer(k->blocks[j], l);
k->blocks[j] = 0;
}
}
m_pieces.erase(i, m_pieces.end());
m_pool.release_memory();
l.unlock();
j.storage->delete_files_impl();
break;
}
}
}
catch (std::exception& e)
@ -343,8 +576,8 @@ namespace libtorrent
// if (!handler) std::cerr << "DISK THREAD: no callback specified" << std::endl;
// else std::cerr << "DISK THREAD: invoking callback" << std::endl;
try { if (handler) handler(ret, j); }
catch (std::exception&) {}
if (handler) m_ios.post(bind(handler, ret, j));
#ifndef NDEBUG
m_current.storage = 0;

View File

@ -3111,6 +3111,9 @@ namespace libtorrent
complete = false;
break;
}
/*
// this invariant is not valid anymore since the completion event
// might be queued in the io service
if (complete && !piece_failed)
{
disk_io_job ret = m_ses.m_disk_thread.find_job(
@ -3118,6 +3121,7 @@ namespace libtorrent
TORRENT_ASSERT(ret.action == disk_io_job::hash || ret.action == disk_io_job::write);
TORRENT_ASSERT(ret.piece == i->index);
}
*/
}
}
// expensive when using checked iterators

View File

@ -48,8 +48,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/torrent.hpp"
#endif
#define TORRENT_PIECE_PICKER_INVARIANT_CHECK INVARIANT_CHECK
//#define TORRENT_PIECE_PICKER_INVARIANT_CHECK
//#define TORRENT_PIECE_PICKER_INVARIANT_CHECK INVARIANT_CHECK
#define TORRENT_PIECE_PICKER_INVARIANT_CHECK
//#define TORRENT_PICKER_LOG

View File

@ -224,7 +224,10 @@ namespace libtorrent
// the number of blocks we want, but it will try to make the picked
// blocks be from whole pieces, possibly by returning more blocks
// than we requested.
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint());
#ifndef NDEBUG
asio::error_code ec;
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
#endif
piece_picker::piece_state_t state;
peer_connection::peer_speed_t speed = c.peer_speed();

View File

@ -277,6 +277,17 @@ namespace libtorrent
return m_impl->status();
}
void session::get_cache_info(sha1_hash const& ih
, std::vector<cached_piece_info>& ret) const
{
m_impl->m_disk_thread.get_cache_info(ih, ret);
}
cache_status session::get_cache_status() const
{
return m_impl->m_disk_thread.status();
}
#ifndef TORRENT_DISABLE_DHT
void session::start_dht(entry const& startup_state)

View File

@ -552,6 +552,8 @@ namespace detail
)
: m_send_buffers(send_buffer_size)
, m_files(40)
, m_io_service()
, m_disk_thread(m_io_service)
, m_half_open(m_io_service)
, m_download_channel(m_io_service, peer_connection::download_channel)
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
@ -807,6 +809,8 @@ namespace detail
// less than 5 seconds unchoke interval is insane
TORRENT_ASSERT(s.unchoke_interval >= 5);
if (m_settings.cache_size != s.cache_size)
m_disk_thread.set_cache_size(s.cache_size);
m_settings = s;
m_files.resize(m_settings.file_pool_size);
if (!s.auto_upload_slots) m_allowed_upload_slots = m_max_uploads;

View File

@ -2765,6 +2765,9 @@ namespace libtorrent
complete = false;
break;
}
// this is no longer valid since the completion event
// may be queued in the io service
/*
if (complete && m_files_checked)
{
disk_io_job ret = m_ses.m_disk_thread.find_job(
@ -2772,6 +2775,7 @@ namespace libtorrent
TORRENT_ASSERT(ret.action == disk_io_job::hash || ret.action == disk_io_job::write);
TORRENT_ASSERT(ret.piece == i->index);
}
*/
}
}

View File

@ -569,7 +569,7 @@ namespace libtorrent
TORRENT_ASSERT(bits == 8 || j == num_bitmask_bytes - 1);
}
piece_struct["bitmask"] = bitmask;
/*
TORRENT_ASSERT(t->filesystem().slot_for(i->index) >= 0);
unsigned long adler
= t->filesystem().piece_crc(
@ -578,7 +578,7 @@ namespace libtorrent
, i->info);
piece_struct["adler32"] = adler;
*/
// push the struct onto the unfinished-piece list
up.push_back(piece_struct);
}

View File

@ -85,7 +85,8 @@ void run_storage_tests(boost::intrusive_ptr<torrent_info> info
// make sure the piece_manager can identify the pieces
{
file_pool fp;
disk_io_thread io;
asio::io_service ios;
disk_io_thread io(ios);
boost::shared_ptr<int> dummy(new int);
boost::intrusive_ptr<piece_manager> pm = new piece_manager(dummy, info
, test_path, fp, io, default_storage_constructor);
@ -130,6 +131,8 @@ void run_storage_tests(boost::intrusive_ptr<torrent_info> info
pm->async_read(r, bind(&on_read_piece, _1, _2, piece2, piece_size));
pm->async_release_files(none);
ios.run();
io.join();
}
}