[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com...
From: |
mldonkey-commits |
Subject: |
[Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com... |
Date: |
Wed, 07 Jun 2006 00:17:46 +0000 |
CVSROOT: /sources/mldonkey
Module name: mldonkey
Changes by: spiralvoice <spiralvoice> 06/06/07 00:17:46
Modified files:
distrib : ChangeLog
src/daemon/common: commonSwarming.ml
src/networks/bittorrent: bTClients.ml
Log message:
patch #5164
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/mldonkey/distrib/ChangeLog?cvsroot=mldonkey&r1=1.874&r2=1.875
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/daemon/common/commonSwarming.ml?cvsroot=mldonkey&r1=1.37&r2=1.38
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/networks/bittorrent/bTClients.ml?cvsroot=mldonkey&r1=1.71&r2=1.72
Patches:
Index: distrib/ChangeLog
===================================================================
RCS file: /sources/mldonkey/mldonkey/distrib/ChangeLog,v
retrieving revision 1.874
retrieving revision 1.875
diff -u -b -r1.874 -r1.875
--- distrib/ChangeLog 6 Jun 2006 23:50:51 -0000 1.874
+++ distrib/ChangeLog 7 Jun 2006 00:17:46 -0000 1.875
@@ -15,6 +15,24 @@
=========
2006/06/07
+5164: CommonSwarming: Pangos WIP5e'
+* When cutting a range, the reciprocal link of the range after the right part
+ still references the left part
+* When cutting a block in two parts can before empty, but then can also before
+ complete (if they have no ranges left)
+* Added bad_writes_is_back patch
+* When find_range can only find ranges already being downloaded, it now first
+ does a quick check to see if there's no other, probably more interesting,
+ blocks remaining. If so, it forces a block change (report no more ranges
left)
+* While it's a good feature in itself, it's probably a workaround for a bug in
+ select_block (?); It seems that blocks oversaturated with sources happen way
+ too often (4 or 5 sources on a single range shouldn't happen).
+* Compute the size of unselected ranges in each blocks, so that sources don't
+ "rush" on blocks just left by a source.
+* Some BAD WRITEs seems to happen because we forget ranges we requested
+ (when switching blocks ?)
+* Replaced call to clear_uploader_ranges by a call to clear_uploader_intervals
+ in BitTorrent support Choke message handler.
5063: EDK: remove duplicate entries in shared_files_new.ini (pango)
5160: Remove stale avifile.ml, clean commonMultimedia logging
5159: Compute magic values only when needed
Index: src/daemon/common/commonSwarming.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonSwarming.ml,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -b -r1.37 -r1.38
--- src/daemon/common/commonSwarming.ml 6 Jun 2006 22:31:18 -0000 1.37
+++ src/daemon/common/commonSwarming.ml 7 Jun 2006 00:17:46 -0000 1.38
@@ -57,8 +57,7 @@
type strategy =
LinearStrategy (* one after the other one *)
-| AdvancedStrategy (* first chunks first, rarest chunks second,
- complete first third, and random final *)
+| AdvancedStrategy
exception VerifierNotReady
@@ -72,7 +71,6 @@
| ForceVerification
| Verification of uid_type array
-(* let debug_all = true *)
let exit_on_error = ref false
let log_prefix = "[cSw]"
@@ -90,15 +88,10 @@
open CommonClient
-(* Worst scenario?: 1 GB splitted in small ranges of 64 KB = 16 000 ranges.
- In eDonkey, ranges are 180 kB long.
-*)
-
(* If we want to become 'multinet', we should:
* there shouldn't be any block_size, instead blocks should correspond
- to the largest blocks which are completely included in one block for
+ to the largest blocks which are completely included in one chunk for
every network.
-* the range_size should be the same for all networks.
* a completed block should not be verified until all the blocks are
completed for all networks.
* swarmers should be loaded before other files, so that they can be
@@ -188,6 +181,8 @@
instead ?
or a balanced tree ? *)
mutable block_remaining : int64; (* amount of bytes missing. *)
+ mutable block_unselected_remaining : int64; (* same, less ranges
+ selected by sources. *)
}
and range = {
@@ -334,8 +329,6 @@
let uploaders_by_num = HU.create 113
-let edonkey_range_size = Int64.of_int (180 * 1024)
-
let swarmer_counter = ref 0
let string_init n f =
@@ -399,6 +392,9 @@
in
r
+let compute_range_size r =
+ r.range_end -- r.range_begin
+
let rec ranges_iter f r =
f r;
match r.range_next with
@@ -447,31 +443,39 @@
let cut_ranges_after b r cut_pos =
let rec iter r =
+ (* after the cut position already ? *)
if r.range_begin >= cut_pos then begin
(match r.range_prev with
- | None -> ()
+ | None ->
+ let b1 = r.range_block in
+ b1.block_ranges <- void_range b1 cut_pos
| Some rp ->
rp.range_next <- None;
r.range_prev <- None);
r
end
+ (* still before the cut position ? *)
else if r.range_end <= cut_pos then
match r.range_next with
| None -> void_range b cut_pos
| Some r -> iter r
else
+ (* across cut position, must split a range *)
(* "right" half *)
let split_r = { r with
+ range_begin = cut_pos;
range_prev = None;
- range_begin = max r.range_begin cut_pos
} in
+ (match split_r.range_next with
+ | None -> ()
+ | Some rr -> rr.range_prev <- Some split_r);
+
(* "left" half *)
- r.range_next <- None;
r.range_end <- cut_pos;
- r.range_begin <- min r.range_begin cut_pos;
+ r.range_next <- None;
if r.range_nuploading <> 0 then
- lprintf_n "WARNING: Splitting a range currently being uploaded, don't
know what to do with range_nuploading :/\n";
+ lprintf_nl "WARNING: Splitting a range currently being uploaded, don't
know what to do with range_nuploading :/";
split_r in
let cut_ranges = iter r in
@@ -534,7 +538,7 @@
(** Return true if ranges fully "cover" their block
("the block is made of holes") *)
-let empty_block b =
+let block_is_empty b =
let rec iter begin_pos r =
r.range_begin = begin_pos &&
(match r.range_next with
@@ -543,6 +547,10 @@
in
iter b.block_begin b.block_ranges
+let block_is_full b =
+ let r = b.block_ranges in
+ r.range_next = None && r.range_begin = r.range_end
+
let iter_intervals s f intervals =
let nchunks = Array.length s.s_blocks in
List.iter (fun (interval_begin, interval_end) ->
@@ -664,7 +672,8 @@
iter (index_s+1) chunk_end new_blocks
else begin
-(* We need to split this block in two parts *)
+ (* chunk_end < block_end
+ We need to split this block in two parts *)
s.s_block_pos.(index_s) <- chunk_end;
match s.s_blocks.(index_s) with
| EmptyBlock | CompleteBlock | VerifiedBlock ->
@@ -686,13 +695,20 @@
block_end = b1.block_end;
block_ranges = b1.block_ranges; (* fixed below *)
block_num = 0; (* fixed below *)
- block_remaining = zero; (* unused ? *)
+ block_remaining = zero; (* fixed below *)
+ block_unselected_remaining = zero; (* fixed below *)
} in
b2.block_ranges <- cut_ranges_after b2 b1.block_ranges chunk_end;
b1.block_end <- chunk_end;
let new_blocks =
- (if empty_block b1 then
+ (if block_is_full b1 then
+(* lprintf "Partial block b1 should become CompleteBlock\n"; *)
+ (
+ CompleteBlock,
+ block_begin,
+ '2'
+ ) else if block_is_empty b1 then
(* lprintf "Partial block b1 should become EmptyBlock\n"; *)
(
EmptyBlock,
@@ -705,11 +721,17 @@
))
:: new_blocks in
- if empty_block b2 then begin
-(* lprintf "Partial block b2 should become EmptyBlock\n"; *)
+ if block_is_full b2 then begin
+ (* lprintf "Partial block b2 should become CompleteBlock\n"; *)
+ s.s_blocks.(index_s) <- CompleteBlock;
+ s.s_verified_bitmap.[index_s] <- '2'
+ end
+ else if block_is_empty b2 then begin
+ (* lprintf "Partial block b2 should become EmptyBlock\n"; *)
s.s_blocks.(index_s) <- EmptyBlock;
s.s_verified_bitmap.[index_s] <- '0';
- end else
+ end
+ else
s.s_blocks.(index_s) <- PartialBlock b2;
iter index_s chunk_end new_blocks
end
@@ -743,7 +765,21 @@
| (b, pos, c) :: tail ->
begin
match b with
- | PartialBlock b -> b.block_num <- i
+ | PartialBlock b ->
+ begin
+ b.block_num <- i;
+ let block_size = compute_block_end s i --
+ compute_block_begin s i in
+ let remaining, unselected_remaining =
+ block_ranges_fold (fun (racc, uracc) r ->
+ let range_size = compute_range_size r in
+ (racc -- range_size,
+ if r.range_nuploading = 0 then
+ uracc -- range_size else uracc)
+ ) (block_size, block_size) b in
+ b.block_remaining <- remaining;
+ b.block_unselected_remaining <- unselected_remaining;
+ end
| EmptyBlock | CompleteBlock | VerifiedBlock -> ()
end;
s.s_blocks.(i) <- b;
@@ -986,14 +1022,18 @@
let close_block_ranges maybe_t s b =
iter_block_ranges (fun r ->
- let added = r.range_end -- r.range_begin in
+ let added = compute_range_size r in
add_file_downloaded maybe_t s added;
b.block_remaining <- b.block_remaining -- added;
+ if r.range_nuploading = 0 then
+ b.block_unselected_remaining <- b.block_unselected_remaining -- added;
r.range_begin <- r.range_end;
r.range_prev <- None;
r.range_next <- None) b;
if b.block_remaining <> 0L then
- lprintf_nl "WARNING: block_remaining should be 0 after close_block_ranges"
+ lprintf_nl "WARNING: block_remaining should be 0 after close_block_ranges";
+ if b.block_unselected_remaining <> 0L then
+ lprintf_nl "WARNING: block_unselected_remaining should be 0 after
close_block_ranges"
(*************************************************************************)
(* *)
@@ -1362,6 +1402,7 @@
let block_begin = compute_block_begin s i in
let block_end = compute_block_end s i in
+ let block_size = block_end -- block_begin in
let rec b = {
block_s = s;
@@ -1369,7 +1410,8 @@
block_end = block_end;
block_ranges = range;
block_num = i;
- block_remaining = block_end -- block_begin;
+ block_remaining = block_size;
+ block_unselected_remaining = block_size;
}
and range = {
@@ -1402,14 +1444,16 @@
if r.range_begin >= interval_begin &&
r.range_begin < interval_end then begin
(* lprintf "... entered\n"; *)
- let new_current_begin =
+ let new_begin =
max (min interval_end r.range_end) r.range_begin in
- let downloaded = new_current_begin -- r.range_begin in
+ let downloaded = new_begin -- r.range_begin in
let b = r.range_block in
let s = b.block_s in
add_file_downloaded maybe_t s downloaded;
b.block_remaining <- b.block_remaining -- downloaded;
- r.range_begin <- new_current_begin;
+ if r.range_nuploading = 0 then
+ b.block_unselected_remaining <- b.block_unselected_remaining --
downloaded;
+ r.range_begin <- new_begin;
if r.range_begin = r.range_end then begin
(* range completed, unlink it *)
(match r.range_next with
@@ -1422,9 +1466,8 @@
match r.range_next with
| Some rr -> (* fix block's first range *)
b.block_ranges <- rr
- | None ->
- (* that was the last remaining range of the block *)
- (match s.s_blocks.(b.block_num) with
+ | None -> (* that was the last remaining range of the block *)
+ match s.s_blocks.(b.block_num) with
| PartialBlock _ | EmptyBlock ->
(match s.s_networks with
| t :: _ ->
@@ -1436,7 +1479,7 @@
set_completed_block (Some t) s b.block_num;
must_verify_block s b.block_num)
| [] -> assert false)
- | _ -> () ));
+ | _ -> () );
r.range_next <- None;
r.range_prev <- None;
end (* else begin
@@ -1690,7 +1733,13 @@
if r.range_nuploading > 0 then
r.range_nuploading <- r.range_nuploading - 1
else
- lprintf_nl "clear_uploader_ranges: some range_nuploading was about to
become negative\n"
+ lprintf_nl "clear_uploader_ranges: some range_nuploading was about to
become negative\n";
+ if r.range_nuploading = 0 then
+ let b = r.range_block in
+ b.block_unselected_remaining <-
+ b.block_unselected_remaining ++ (compute_range_size r);
+ if b.block_unselected_remaining > b.block_remaining then
+ lprintf_nl "clear_uploader_ranges: block_unselected_remaining larger
than block_remaining!";
) up.up_ranges;
up.up_ranges <- []
@@ -1701,6 +1750,8 @@
let num = b.block_num in
let t = up.up_t in
let s = t.t_s in
+ if debug_all then
+ lprintf_nl "Client %d unselect %d" (client_num up.up_client) num;
if s.s_nuploading.(num) > 0 then
s.s_nuploading.(num) <- s.s_nuploading.(num) - 1
else
@@ -1888,8 +1939,9 @@
choice_user_priority : int;
choice_nuploaders : int;
choice_remaining : int64;
+ choice_unselected_remaining : int64;
choice_remaining_per_uploader : int64; (* algo 1 only *)
- choice_saturated : bool; (* has enough uploades *) (* algo 2 only *)
+ choice_saturated : bool; (* has enough uploaders *) (* algo 2 only *)
choice_other_complete : int Lazy.t; (* ...blocks in the same chunk *)
choice_availability : int;
}
@@ -1899,6 +1951,7 @@
choice_user_priority = 0;
choice_nuploaders = 0;
choice_remaining = 0L;
+ choice_unselected_remaining = 0L;
choice_remaining_per_uploader = 0L; (* algo 1 only *)
choice_saturated = true; (* algo 2 only *)
choice_other_complete = lazy 0;
@@ -1923,19 +1976,7 @@
done;
!r
-(* DEBUGGING *)
-let delta_needed = ref 0
-let delta_undecided = ref 0
-
let select_block up =
-(* DEBUGGING *)
- let compare_choices_saturation = ref 0 in
- let compare_choices_priority = ref 0 in
- let compare_choices_rarity = ref 0 in
- let compare_choices_completion = ref 0 in
- let compare_choices_siblings = ref 0 in
- let compare_choices_failure = ref 0 in
-
let t = up.up_t in
let s = t.t_s in
try
@@ -1980,6 +2021,56 @@
| 2 -> verification_available && t.t_nverified_chunks < 2
| _ -> assert false in
+ let evaluate_choice n b =
+ let nchunk = my_t.t_chunk_of_block.(b) in
+ let block_begin = compute_block_begin s b in
+ let block_end = compute_block_end s b in
+ let size = block_end -- block_begin in
+ let remaining, unselected_remaining = match s.s_blocks.(b) with
+ | EmptyBlock -> size, size
+ | PartialBlock b -> b.block_remaining, b.block_unselected_remaining
+ | CompleteBlock | VerifiedBlock -> 0L, 0L in
+ let nuploaders = s.s_nuploading.(b) in
+ {
+ choice_num = n;
+ choice_user_priority = (* priority bitmap here instead ? *)
+ if block_begin < preview_beginning then 3 else
+ if block_end > preview_end then 2 else 1;
+ choice_nuploaders = nuploaders;
+ choice_remaining = remaining;
+ choice_unselected_remaining = unselected_remaining;
+ choice_remaining_per_uploader =
+ if !!swarming_block_selection_algorithm = 1 then
+ unselected_remaining //
+ (Int64.of_int (nuploaders + 1)) (* planned value *)
+ else 0L;
+ choice_saturated =
+ if !!swarming_block_selection_algorithm = 2 then
+ unselected_remaining <= Int64.of_int nuploaders **
data_per_source
+ (*
+ nuploaders >= Int64.to_int (
+ Int64.pred (
+ unselected_remaining ** Int64.of_int !!sources_per_chunk ++
size)
+ // size)
+ *)
+ else true;
+ choice_other_complete = completed_blocks_in_chunk.(nchunk);
+ choice_availability = s.s_availability.(b);
+ } in
+
+ let print_choice c =
+ lprintf_nl "choice %d:%d priority:%d nup:%d rem:%Ld rmu:%Ld rpu:%Ld
sat:%B sib:%s av:%d"
+ c.choice_num up.up_complete_blocks.(c.choice_num)
+ c.choice_user_priority
+ c.choice_nuploaders
+ c.choice_remaining
+ c.choice_unselected_remaining
+ c.choice_remaining_per_uploader
+ c.choice_saturated
+ (if Lazy.lazy_is_val c.choice_other_complete then
+ string_of_int (Lazy.force c.choice_other_complete) else "?")
+ c.choice_availability in
+
(** > 0 == c1 is best, < 0 = c2 is best, 0 == they're equivalent *)
let compare_choices1 c1 c2 =
@@ -1989,17 +2080,11 @@
c2.choice_remaining_per_uploader < data_per_source then
compare c1.choice_remaining_per_uploader
c2.choice_remaining_per_uploader else 0 in
- if cmp <> 0 then begin
- incr compare_choices_saturation;
- cmp
- end else
+ if cmp <> 0 then cmp else
(* Do what Master asked for *)
let cmp = compare c1.choice_user_priority c2.choice_user_priority in
- if cmp <> 0 then begin
- incr compare_choices_priority;
- cmp
- end else
+ if cmp <> 0 then cmp else
(* Pick really rare gems: if average availability of all
blocks is higher than 5 connected sources, pick in
@@ -2011,18 +2096,17 @@
(c1.choice_availability <= 3 || c2.choice_availability <= 3) then
compare c2.choice_availability c1.choice_availability
else 0 in
- if cmp <> 0 then begin
- incr compare_choices_rarity;
- cmp
- end else
+ if cmp <> 0 then cmp else
(* try to quickly complete blocks *)
let cmp =
- compare c2.choice_remaining c1.choice_remaining in
- if cmp <> 0 then begin
- incr compare_choices_completion;
- cmp
- end else
+ match c1.choice_unselected_remaining,
+ c2.choice_unselected_remaining with
+ | 0L, 0L -> 0
+ | 0L, _ -> -1
+ | _, 0L -> 1
+ | ur1, ur2 -> compare ur2 ur1 in
+ if cmp <> 0 then cmp else
(* try to quickly complete (and validate) chunks;
if there's only one frontend, each chunk has only one
@@ -2032,53 +2116,38 @@
compare (Lazy.force c1.choice_other_complete)
(Lazy.force c2.choice_other_complete)
else 0 in
- if cmp <> 0 then begin
- incr compare_choices_siblings;
- cmp
- end else
+ if cmp <> 0 then cmp else
- begin
(* Can't tell *)
- incr compare_choices_failure;
- 0
- end in
+ 0 in
let compare_choices2 c1 c2 =
+ (* "RULES" *)
+ (* Avoid stepping on each other's feet *)
+ let cmp =
+ match c1.choice_unselected_remaining,
+ c2.choice_unselected_remaining with
+ | 0L, 0L -> 0
+ | _, 0L -> 1
+ | 0L, _ -> -1
+ | _, _ -> 0 in
+ if cmp <> 0 then cmp else
(* avoid overly unbalanced situations *)
let cmp =
match c1.choice_saturated, c2.choice_saturated with
| false, false -> 0
- | true, false -> -1
| false, true -> 1
- | true, true ->
- let result =
- (* both are saturated, try to balance situation *)
- incr delta_needed;
- let delta =
- c1.choice_remaining ** Int64.of_int c2.choice_nuploaders --
- c2.choice_remaining ** Int64.of_int c1.choice_nuploaders in
- if delta > c2.choice_remaining then 1
- else if delta < Int64.neg c1.choice_remaining then -1
- else begin
- (* either way we'll unbalance the situation *)
- incr delta_undecided;
- 0
- end in
- lprintf_nl "compare_choices needed delta %d times, which
couldn't decide %d times" !delta_needed !delta_undecided;
- result in
- if cmp <> 0 then begin
- incr compare_choices_saturation;
- cmp
- end else
+ | true, false -> -1
+ | true, true -> 0 in
+ if cmp <> 0 then cmp else
+ (* "WISHES" *)
(* Do what Master asked for *)
let cmp = compare c1.choice_user_priority c2.choice_user_priority in
- if cmp <> 0 then begin
- incr compare_choices_priority;
- cmp
- end else
+ if cmp <> 0 then cmp else
+ (* "OPTIMIZATIONS" *)
(* Pick really rare gems: if average availability of all
blocks is higher than 5 connected sources, pick in
priority blocks present in at most 3 connected sources;
@@ -2086,21 +2155,12 @@
let cmp =
if not need_to_complete_some_blocks_quickly &&
mean_availability > 5 &&
- (c1.choice_availability <= 3 || c2.choice_availability <= 3) then
- compare c2.choice_availability c1.choice_availability
+ (c1.choice_availability <= 3 || c2.choice_availability
+ <= 3) then
+ compare c2.choice_availability
+ c1.choice_availability
else 0 in
- if cmp <> 0 then begin
- incr compare_choices_rarity;
- cmp
- end else
-
- (* try to quickly complete blocks *)
- let cmp =
- compare c2.choice_remaining c1.choice_remaining in
- if cmp <> 0 then begin
- incr compare_choices_completion;
- cmp
- end else
+ if cmp <> 0 then cmp else
(* try to quickly complete (and validate) chunks;
if there's only one frontend, each chunk has only one
@@ -2110,16 +2170,17 @@
compare (Lazy.force c1.choice_other_complete)
(Lazy.force c2.choice_other_complete)
else 0 in
- if cmp <> 0 then begin
- incr compare_choices_siblings;
- cmp
- end else
+ if cmp <> 0 then cmp else
- begin
+ (* try to quickly complete blocks *)
+ let cmp =
+ compare c2.choice_unselected_remaining
+ c1.choice_unselected_remaining in
+ if cmp <> 0 then cmp else
+
+ (* "DEFAULT" *)
(* Can't tell *)
- incr compare_choices_failure;
- 0
- end in
+ 0 in
let compare_choices =
match !!swarming_block_selection_algorithm with
@@ -2131,49 +2192,15 @@
subarray_fold_lefti (fun ((best_choices, specimen) as acc) n b ->
(* priority bitmap <> 0 here ? *)
if not (should_download_block s b) then acc else
- let nchunk = my_t.t_chunk_of_block.(b) in
- let block_begin = compute_block_begin s b in
- let block_end = compute_block_end s b in
- let size = block_end -- block_begin in
- let remaining = match s.s_blocks.(b) with
- | EmptyBlock -> size
- | PartialBlock b -> b.block_remaining
- | CompleteBlock | VerifiedBlock -> 0L in
- let nuploaders = s.s_nuploading.(b) in
- let this_choice = {
- choice_num = n;
- choice_user_priority = (* priority bitmap here instead ? *)
- if block_begin < preview_beginning then 3 else
- if block_end > preview_end then 2 else 1;
- choice_nuploaders = nuploaders;
- choice_remaining = remaining;
- choice_remaining_per_uploader =
- if !!swarming_block_selection_algorithm = 1 then
- remaining //
- (Int64.of_int (nuploaders + 1)) (* planned value *)
- else 0L;
- choice_saturated =
- if !!swarming_block_selection_algorithm = 2 then
- not need_to_complete_some_blocks_quickly &&
- remaining <= Int64.of_int nuploaders ** data_per_source
- (*
- nuploaders >= Int64.to_int (
- Int64.pred (
- remaining ** Int64.of_int !!sources_per_chunk ++ size)
- // size)
- *)
- else true;
- choice_other_complete = completed_blocks_in_chunk.(nchunk);
- choice_availability = s.s_availability.(b);
- } in
+ let this_choice = evaluate_choice n b in
match best_choices with
| [] -> [n], this_choice
| _ :: _ ->
(* all the choices in the accumulator are supposed to
be equivalent, compare against the specimen *)
let cmp = compare_choices this_choice specimen in
- if cmp > 0 then [n], this_choice
- else if cmp < 0 then acc
+ if cmp < 0 then acc
+ else if cmp > 0 then [n], this_choice
else n :: best_choices, specimen
) ([], dummy_choice) up.up_complete_blocks 0 (up.up_ncomplete - 1) in
(* what about up_partial_blocks ?
@@ -2181,23 +2208,6 @@
fallback below *)
if debug_all then begin
- let nbest_choices = List.length best_choices in
- lprintf_nl "compare_choices: %d choices left based on saturation:%d
priority:%d rarity:%d completion:%d siblings:%d failed:%d"
- nbest_choices
- !compare_choices_saturation !compare_choices_priority
- !compare_choices_rarity !compare_choices_completion
- !compare_choices_siblings !compare_choices_failure;
- let print_choice c =
- lprintf_nl "selected %d:%d priority:%d nup:%d rem:%Ld rpu:%Ld
sat:%B sib:%s av:%d"
- c.choice_num up.up_complete_blocks.(c.choice_num)
- c.choice_user_priority
- c.choice_nuploaders
- c.choice_remaining
- c.choice_remaining_per_uploader
- c.choice_saturated
- (if Lazy.lazy_is_val c.choice_other_complete then
- string_of_int (Lazy.force c.choice_other_complete) else "?")
- c.choice_availability in
print_choice specimen
end;
@@ -2212,6 +2222,40 @@
if debug_all then lprintf_nl "\nBlockFound %d"
up.up_complete_blocks.(n);
+
+(*
+ (* DEBUG *)
+ let block_num = up.up_complete_blocks.(n) in
+ let probably_buggy =
+ match s.s_blocks.(block_num) with
+ | EmptyBlock -> false
+ | PartialBlock b ->
+ block_ranges_for_all (fun r ->
+ r.range_nuploading > 0) b
+ | CompleteBlock | VerifiedBlock ->
+ true in
+ if probably_buggy then begin
+ lprintf_nl "Probably buggy choice:";
+ subarray_fold_lefti (fun () n b ->
+ if should_download_block s b then
+ let this_choice = evaluate_choice n b in
+ if List.mem n best_choices then lprintf "** "
+ else lprintf " ";
+ print_choice this_choice;
+ match s.s_blocks.(b) with
+ | EmptyBlock | CompleteBlock | VerifiedBlock -> ()
+ | PartialBlock b ->
+ let total_uploading =
+ block_ranges_fold (fun acc r ->
+ lprintf "%d " r.range_nuploading;
+ acc + r.range_nuploading) 0 b in
+ lprintf "total=%d" total_uploading;
+ lprint_newline ()
+ ) () up.up_complete_blocks 0 (up.up_ncomplete - 1);
+ end;
+ (* /DEBUG *)
+*)
+
permute_and_return up n
with Not_found ->
if !verbose_swarming then
@@ -2252,12 +2296,19 @@
| None -> ()
| Some b ->
let num = b.block_num in
- s.s_nuploading.(num) <- s.s_nuploading.(num) - 1;
+ if debug_all then
+ lprintf_nl "Client %d unselected %d" (client_num up.up_client)
num;
+ if s.s_nuploading.(num) > 0 then
+ s.s_nuploading.(num) <- s.s_nuploading.(num) - 1
+ else
+ lprintf_nl "find_block: s_nuploading was about to become
negative";
up.up_block <- None;
);
let b, block_begin, block_end = select_block up in
let num = b.block_num in
+ if debug_all then
+ lprintf_nl "Client %d selected %d" (client_num up.up_client) num;
s.s_nuploading.(num) <- s.s_nuploading.(num) + 1;
up.up_block <- Some b;
up.up_block_begin <- block_begin;
@@ -2277,7 +2328,18 @@
r.range_begin < r.range_end) up.up_ranges in
up.up_ranges <- not_completed_ranges;
List.iter (fun (_,_,r) ->
- r.range_nuploading <- r.range_nuploading - 1) completed_ranges
+ if r.range_nuploading > 0 then
+ r.range_nuploading <- r.range_nuploading - 1
+ else
+ lprintf_nl "remove_completed_uploader_ranges: range_nuploading
+ was about to become negative!";
+ if r.range_nuploading = 0 then
+ let b = r.range_block in
+ b.block_unselected_remaining <-
+ b.block_unselected_remaining ++ (compute_range_size r);
+ if b.block_unselected_remaining > b.block_remaining then
+ lprintf_nl "remove_completed_uploader_ranges:
block_unselected_remaining is larger than block_remaining";
+ ) completed_ranges
(** uploader accessors *)
@@ -2309,8 +2371,8 @@
(** Find a range to upload from [up], that is at most [range_size]
bytes long (split some range if necessary) *)
-(* Is merging at all useful ? Once range starts downloading, they can
- no longer be merged, so it should be very rare... *)
+(* Is merging at all useful ? Once next range starts downloading, they
+ can no longer be merged, so it should be rare... *)
let allow_merge_ranges = true
type ranges_cluster = {
@@ -2325,6 +2387,9 @@
cluster_size = 0L
}
+let is_dummy_cluster cluster =
+ cluster.cluster_ranges = []
+
let find_range up range_size =
(** merge two consecutive ranges in the first, if possible;
@@ -2364,7 +2429,8 @@
| FileShared
| FileNew
| FileDownloaded ->
- lprintf_nl "find_range: file %s in bad state %s" t.t_s.s_filename
(string_of_state (file_state t.t_file));
+ lprintf_nl "find_range: file %s in bad state %s"
+ t.t_s.s_filename (string_of_state (file_state t.t_file));
raise Not_found
| FileDownloading
| FileQueued ->
@@ -2386,12 +2452,10 @@
else
(* find if they're ranges to merge ahead *)
let rec iter_cluster r cluster =
- if debug_all then
- lprintf_nl "[%Ld-%Ld] " r.range_begin r.range_end;
let cluster = { cluster with
cluster_ranges = r :: cluster.cluster_ranges;
cluster_size = cluster.cluster_size ++
- (r.range_end -- r.range_begin)
+ (compute_range_size r)
} in
if not allow_merge_ranges ||
cluster.cluster_size >= range_size then cluster
@@ -2409,7 +2473,7 @@
cluster_nuploading = r.range_nuploading } in
if debug_all then
lprint_newline ();
- if acc.cluster_ranges = [] then cluster
+ if is_dummy_cluster acc then cluster
else
(* find a range with as few uploaders as possible *)
let cmp = compare acc.cluster_nuploading
@@ -2419,7 +2483,7 @@
(* fast exit, and why I didn't use an iterator :/
Could have used an exception, but I don't like that ;) *)
- if best_cluster.cluster_ranges <> [] &&
+ if not (is_dummy_cluster best_cluster) &&
best_cluster.cluster_nuploading = 0 then best_cluster
else
match r.range_next with
@@ -2427,6 +2491,28 @@
| Some rr -> iter best_cluster rr in
let best_cluster = iter dummy_ranges_cluster b.block_ranges in
+ if not (is_dummy_cluster best_cluster) &&
+ best_cluster.cluster_nuploading > 0 then begin
+ (* it seems they're only sucky choices left on that block, is
+ there really nothing else better elsewhere ? *)
+ let s = b.block_s in
+ let current_block = b.block_num in
+ for i = 0 to up.up_ncomplete - 1 do
+ let block = up.up_complete_blocks.(i) in
+ if block <> current_block then
+ if should_download_block s block then (* priority bitmap <> 0 here
? *)
+ let partial_found = match s.s_blocks.(block) with
+ | EmptyBlock -> true
+ | CompleteBlock | VerifiedBlock -> false
+ | PartialBlock b -> b.block_unselected_remaining > 0L in
+ if partial_found then begin
+ if debug_all || !verbose then
+ lprintf_nl "find_range: Client %d better switch block now!"
+ (client_num up.up_client);
+ raise Not_found
+ end
+ done
+ end;
match List.rev best_cluster.cluster_ranges with
| [] ->
if debug_all then
@@ -2438,14 +2524,24 @@
split_range r (min (r.range_begin ++ range_size)
up.up_block_end);
if debug_all then begin
- lprintf "=> [%Ld-%Ld], left:" r.range_begin r.range_end;
- iter_block_ranges (fun r ->
- lprintf " [%Ld-%Ld]" r.range_begin r.range_end
+ lprintf "=> ";
+ iter_block_ranges (fun rr ->
+ let selected = if rr == r then "*" else "" in
+ lprintf " %s[%Ld-%Ld]:%d%s" selected
+ rr.range_begin rr.range_end rr.range_nuploading
+ selected
) b;
lprint_newline ();
end;
let key = r.range_begin, r.range_end, r in
up.up_ranges <- up.up_ranges @ [key];
+ if r.range_nuploading = 0 then begin
+ let b = r.range_block in
+ b.block_unselected_remaining <-
+ b.block_unselected_remaining -- (compute_range_size r);
+ if b.block_unselected_remaining < 0L then
+ lprintf_nl "find_range: block_unselected_remaining is negative!";
+ end;
r.range_nuploading <- r.range_nuploading + 1;
key
@@ -2462,13 +2558,16 @@
assert (string_len >= 0);
assert (string_begin + string_len <= String.length str);
-(*
- let debug_bad_write r string_pos =
- if !verbose then begin
let t = up.up_t in
let s = t.t_s in
- lprintf_nl "BAD WRITE in %s for range %Ld-%Ld (string_pos %d)"
- (file_best_name t.t_file) r.range_begin r.range_end string_pos;
+
+ let debug_bad_write unexpected_intervals =
+ if !verbose then begin
+ lprintf "BAD WRITE of %d in %s:"
+ (client_num up.up_client) (file_best_name t.t_file);
+ List.iter (fun (i_begin, i_end) ->
+ lprintf " %Ld-%Ld" i_begin i_end) unexpected_intervals;
+ lprint_newline ();
lprintf_nl " received: file_pos:%Ld string:%d %d"
file_begin string_begin string_len;
lprintf_nl " ranges:";
@@ -2499,21 +2598,44 @@
let br = b.block_ranges in
lprintf " first range: %Ld(%Ld)"
br.range_begin
- (br.range_end -- br.range_begin);
+ (compute_range_size br);
lprint_newline ();
) up.up_ranges
end;
- if !exit_on_error then exit 2 in *)
+ if !exit_on_error then exit 2 in
if string_len > 0 then
let file_end = file_begin ++ (Int64.of_int string_len) in
-
if !verbose_swarming then
lprintf_nl "received on %Ld-%Ld" file_begin file_end;
-(* TODO: check that everything we received has been required *)
- let t = up.up_t in
- let s = t.t_s in
+ (* DEBUG *)
+ let intervals_out =
+ let remove_interval intervals interval_begin interval_end =
+ let rec remove acc intervals =
+ match intervals with
+ | [] -> List.rev acc
+ | ((fi_begin, fi_end) as first_interval) :: others ->
+ if fi_begin >= interval_end then
+ List.rev_append acc intervals
+ else if fi_end <= interval_begin then
+ remove (first_interval :: acc) others
+ else
+ remove (
+ let acc = if fi_begin < interval_begin then
+ (fi_begin, interval_begin) :: acc else acc in
+ let acc = if fi_end > interval_end then
+ (interval_end, fi_end) :: acc else acc in
+ acc) others in
+ remove [] intervals in
+ List.fold_left (fun acc (_, _, r) ->
+ remove_interval acc r.range_begin r.range_end
+ ) [(file_begin, file_end)] up.up_ranges in
+ if intervals_out <> [] then
+ debug_bad_write intervals_out;
+
+ let file_end = min file_end s.s_size in
+
match file_state t.t_file with
| FilePaused
| FileAborted _
@@ -2536,12 +2658,6 @@
let string_pos = string_begin +
Int64.to_int (r.range_begin -- file_begin) in
let string_length = Int64.to_int written_len in
- (* None of those conditions can happen anymore *)
-(* if string_pos < 0 ||
- string_pos < string_begin ||
- string_len < string_length then
- debug_bad_write r string_pos
- else *)
if string_length > 0 then
match s.s_networks with
| [] -> assert false
@@ -2554,6 +2670,8 @@
) up.up_ranges;
remove_completed_uploader_ranges up
with e ->
+ lprintf_nl "Exception %s while receiving data"
+ (Printexc2.to_string e);
remove_completed_uploader_ranges up;
raise e
Index: src/networks/bittorrent/bTClients.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTClients.ml,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -b -r1.71 -r1.72
--- src/networks/bittorrent/bTClients.ml 25 May 2006 19:47:25 -0000
1.71
+++ src/networks/bittorrent/bTClients.ml 7 Jun 2006 00:17:46 -0000
1.72
@@ -994,7 +994,7 @@
if !verbose_msg_clients then lprintf_nl "%s:%d with software
%s : Choke send, but no client bitmap"
(Ip.to_string ip) port (brand_to_string c.client_brand)
| Some up ->
- CommonSwarming.clear_uploader_ranges up
+ CommonSwarming.clear_uploader_intervals up
end;
c.client_ranges_sent <- [];
c.client_range_waiting <- None;
- [Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com..., mldonkey-commits, 2006/06/06
- [Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com..., mldonkey-commits, 2006/06/06
- [Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com..., mldonkey-commits, 2006/06/06
- [Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com...,
mldonkey-commits <=
- [Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com..., mldonkey-commits, 2006/06/09
- [Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com..., mldonkey-commits, 2006/06/11
- [Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com..., mldonkey-commits, 2006/06/11
- [Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com..., mldonkey-commits, 2006/06/11
- [Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com..., mldonkey-commits, 2006/06/12
- [Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com..., mldonkey-commits, 2006/06/12
- [Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com..., mldonkey-commits, 2006/06/12
- [Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com..., mldonkey-commits, 2006/06/12
- [Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com..., mldonkey-commits, 2006/06/12
- [Mldonkey-commits] mldonkey distribChangeLog src/daemon/common/com..., mldonkey-commits, 2006/06/15