1 (* Copyright 2003, Denis Fortin
3 This file is part of mldonkey.
5 mldonkey is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 mldonkey is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with mldonkey; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 (*given some files choose the next uploaders based on their behavior
36 Will choose max_uploaders_per_torrent uploaders for each file in list
37 fun_comp is the function use to classify clients
39 let choose_next_uploaders files fun_comp
=
40 let full_list = ref ([] : BTTypes.client list
)
42 (*constructs a list of i items max with all
43 orl items + some l items *)
44 let orig_num = List.length orl
in
45 if orig_num < i
&& i
> 0 then
46 let keep,rest
= cut
(i
- orig_num) l
in
52 let max_list = ref ([] : BTTypes.client list
) in
54 let possible_uploaders = ref ([] : BTTypes.client list
) in
55 Hashtbl.iter
(fun _ c
->
57 possible_uploaders := (c
::!possible_uploaders);
59 if !verbose_upload
then
60 lprintf_nl
"clients num %d as possible uploaders for file %s" (List.length
!possible_uploaders) f
.file_name
;
61 (*Interested clients with a connection*)
62 let filtl = List.filter
(fun c
-> c
.client_interested
== true
63 && (c
.client_sock
!= NoConnection
)
64 ) !possible_uploaders in
65 (*sort by biggest contributor*)
66 let sortl = List.sort fun_comp
filtl in
67 (*add max_uploaders_per_torrent-1 from the best*)
68 let to_add,next
= keepn
!max_list sortl (!!max_uploaders_per_torrent
- 1) in
70 (* clients in optim are current optimistic uploaders (30 seconds) *)
71 let optim,notoptim
= List.partition
( fun a
->
72 (Rate.ratesince a
.client_upload_rate
) > 0
73 && a
.client_last_optimist
+ 30 > last_time
()
75 let notoptim = List.sort
(fun a b
-> compare a
.client_last_optimist b
.client_last_optimist
) notoptim in
76 (*add at least one optimistic uploader*)
77 let to_add,next
= keepn
!max_list (optim) (!!max_uploaders_per_torrent
) in
79 (*fill up with not optimistic uploaders*)
80 let to_add,_
= keepn
!max_list (notoptim) (!!max_uploaders_per_torrent
) in
81 full_list := !full_list @ to_add;
82 if !verbose_upload
then
84 lprintf_n
"potential uploaders count: %d list: [" (List.length
to_add);
86 let (ip
,port
) = cr
.client_host
in
87 lprintf
" %s:%d" (Ip.to_string ip
) port
;
96 let choose_best_downloaders files
=
97 (*sort: left to download, then priority*)
98 let files = List.stable_sort
100 ((file_size a
) -- (match a
.file_swarmer
with
103 CommonSwarming.downloaded swarmer
))
104 ((file_size b
) -- (match b
.file_swarmer
with
107 CommonSwarming.downloaded swarmer
))
109 let files = List.stable_sort
111 (CommonFile.file_priority
(CommonFile.as_file b
.file_file
))
112 (CommonFile.file_priority
(CommonFile.as_file a
.file_file
))
114 (*use sort function that puts the client we download best from on top*)
115 choose_next_uploaders files (fun a b
-> Rate.compare b
.client_downloaded_rate
116 a
.client_downloaded_rate
)
119 let choose_best_uploaders files =
120 (*use sort function that puts the client we upload best to on top*)
121 choose_next_uploaders files (fun a b
-> Rate.compare b
.client_upload_rate
122 a
.client_upload_rate
)
125 let choose_uploaders files =
126 (*list of new uploaders from the files we download and the files we seed*)
128 ( (choose_best_downloaders (List.filter
129 (fun f
-> file_state f
= FileDownloading
)
131 @ (choose_best_uploaders (List.filter
132 (fun f
-> file_state f
= FileShared
)
135 (*do some debug output and choose the first max_bt_uploaders from the list*)
137 if !verbose_upload
then
139 lprintf_n
"next_uploaders: %d list: [" (List.length
next_uploaders);
141 let (ip
,port
) = cr
.client_host
in
142 lprintf
" %s:%d" (Ip.to_string ip
) port
;
146 if (List.length
next_uploaders) > !!max_bt_uploaders
then
147 let keep,rest
= List2.cut
!!max_bt_uploaders
next_uploaders in
149 if !verbose_upload
then
151 lprintf_n
"cut next_uploaders: %d list: [" (List.length
keep);
153 let (ip
,port
) = cr
.client_host
in
154 lprintf
" %s:%d" (Ip.to_string ip
) port
;