diff options
Diffstat (limited to 'seggetd/connection.cpp')
-rw-r--r-- | seggetd/connection.cpp | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/seggetd/connection.cpp b/seggetd/connection.cpp new file mode 100644 index 0000000..88f6069 --- /dev/null +++ b/seggetd/connection.cpp @@ -0,0 +1,350 @@ +/* +* Copyright (C) 2010 Robin H.Johnson, Ovechko Kostyantyn <fastinetserver@gmail.com>. +* +* Project: IDFetch. +* Developer: Ovechko Kostyantyn Olexandrovich (Kharkiv State Technical University of Construction and Architecture, Ukraine). +* Mentor: Robin H. Johnson (Gentoo Linux: Developer, Trustee & Infrastructure Lead). +* Mentoring organization: Gentoo Linux. +* Sponsored by GSOC 2010. +* +* This file is part of Segget. +* +* Segget is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* Segget is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with Segget; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "connection.h" +#include "utils.h" +#include "settings.h" + +long script_waiting_connection_num=-1; +uint Tconnection::total_connections=0; +Tconnection connection_array[MAX_CONNECTS]; + +void init_connections(){ + for (ulong connection_num=0; connection_num<MAX_CONNECTS; connection_num++){ + connection_array[connection_num].connection_num=connection_num; + }; +} + +int Tconnection::start(CURLM *cm, uint network_number, uint distfile_num, Tsegment *started_segment, uint best_mirror_num){ + try{ + segment=started_segment; + debug("Starting connection for distfile: "+segment->parent_distfile->name); + mirror_num=best_mirror_num; + network_num=network_number; + total_dld_bytes=0; + bytes_per_last_interval=0; + gettimeofday(&start_time,NULL); + debug("Connecting network"+toString(network_num)); + + segment->parent_distfile->set_status(DDOWNLOADING); + + if (network_array[network_num].network_mode==MODE_PROXY_FETCHER){ + connection_start_time_network_phase_for_pf_networks=segment->parent_distfile->network_distfile_brokers_array[network_num].phase; + } + + Tmirror *Pcurr_mirror; + switch (network_array[network_num].network_mode){ + case MODE_REMOTE:{ + url=segment->parent_distfile->url_list[mirror_num]; + Pcurr_mirror=find_mirror(strip_mirror_name(url)); + break; + } + case MODE_CORAL_CDN:{ + url=convert_to_coral_cdn_url(segment->parent_distfile->url_list[mirror_num]); + Pcurr_mirror=find_mirror(strip_mirror_name(url)); + break; + } + default:{ + Pcurr_mirror=&network_array[network_num].benchmarked_mirror_list[mirror_num]; + url=Pcurr_mirror->url+segment->parent_distfile->name; + } + } + debug(" URL:"+url); + + if (run_user_python_script(connection_num)){ + if (segment->parent_distfile->active_connections_num<=0){ + segment->parent_distfile->set_status(DSCRIPTREJECTED); + } + return REJECTED_BY_USER_PYTHON_SCRIPT; + } + stats.active_connections_counter++; + ulong segment_start_result=segment->start(cm, connection_num, network_num, distfile_num, url); + if (segment_start_result){ + return segment_start_result; + }else{ + segment->parent_distfile->active_connections_num++; + active=true; + Pcurr_mirror->start(); + network_array[network_num].connect(); + } + debug("Started connection for distfile: "+segment->parent_distfile->name); + return 0; + }catch(...){ + error_log("Error in connection.cpp: start()"); + } + return ERROR_WHILE_PREPARING_CONNECTION; +} +/* +string explain_curl_error(int error_code){ + try{ + //curl_easy_strerror( + }catch(...){ + error_log("Error in connection.cpp: explain_curl_error()"); + } + return "Error in connection.cpp: explain_curl_error()"; +} +*/ +void Tconnection::stop(CURLcode connection_result){ + try{ + stats.active_connections_counter--; + Tmirror *Pcurr_mirror; + switch (network_array[network_num].network_mode){ + case MODE_REMOTE: + case MODE_CORAL_CDN:{ + Pcurr_mirror=find_mirror(strip_mirror_name(url)); + break; + } + default:{ + Pcurr_mirror=&network_array[network_num].benchmarked_mirror_list[mirror_num]; + } + } + debug("Finished connection for distfile: "+segment->parent_distfile->name+" Segment#:"+toString(segment->segment_num)+" Network#"+toString(network_num)+" Status: "+toString(connection_result)); + if (connection_result){ + string error_str=curl_easy_strerror(connection_result); + debug(" ERROR "+toString(connection_result)+": "+error_str); + error_log("Finished connection for distfile: "+segment->parent_distfile->name+" Segment#:"+toString(segment->segment_num)+" Network#"+toString(network_num)+" Status: "+toString(connection_result)); + error_log(" ERROR "+toString(connection_result)+": "+error_str); + } + active=false; + network_array[network_num].disconnect(); +// network_array[network_num].benchmarked_mirror_list[mirror_num].stop(); + segment->segment_file.close(); + if (connection_result==0){ + if (! segment->segment_verification_is_ok()){ + connection_result=CURLE_READ_ERROR; + Pcurr_mirror->stop(time_left_since(connection_array[connection_num].start_time),0); + debug("curl_lies - there is a problem downloading segment"); + error_log("curl_lies - there is a problem downloading segment"); + }else{ + Pcurr_mirror->stop(time_left_since(connection_array[connection_num].start_time),segment->segment_size); + } + }else{ + Pcurr_mirror->stop(time_left_since(connection_array[connection_num].start_time),0); + } + segment->parent_distfile->active_connections_num--; + + msg_clean_connection(connection_num); + +/* + Tmirror *Pcurr_mirror; + if (network_array[network_num].network_mode==MODE_LOCAL){ + Pcurr_mirror=&network_array[network_num].benchmarked_mirror_list[mirror_num]; + prnt_distfile->network_distfile_brokers_array[network_num].mirror_fails_vector[mirror_num]=true; +// find_mirror(strip_mirror_name(segment->url)); + }else{ + Pcurr_mirror=find_mirror(strip_mirror_name(segment->url)); + } +*/ + debug("before gettimeofday"); + timeval now_time; + gettimeofday(&now_time,NULL); + + if (connection_result!=0){ + stats.fails_counter++; + switch (network_array[network_num].network_mode){ + case MODE_LOCAL:{ + // prnt_distfile->network_distfile_brokers_array[network_num].mirror_fails_vector[mirror_num]=true; + debug("before setting mirror fail"); + segment->parent_distfile->network_distfile_brokers_array[network_num].local_mirror_failed(mirror_num); + debug("after setting mirror fail"); + // find_mirror(strip_mirror_name(segment->url)); + break; + } + case MODE_PROXY_FETCHER:{ + // prnt_distfile->network_distfile_brokers_array[network_num].mirror_fails_vector[mirror_num]=true; + if (connection_start_time_network_phase_for_pf_networks==E_USE_AS_LOCAL_MIRRORS){ + segment->parent_distfile->network_distfile_brokers_array[network_num].local_mirror_failed(mirror_num); + }else{ // proxy-fetcher mirror failed, if everything correct it must be in phase E_PROXY_FETCHER_DOWNLOADED, + segment->parent_distfile->network_distfile_brokers_array[network_num].proxy_fetcher_mirror_failed(mirror_num); + } + // find_mirror(strip_mirror_name(segment->url)); + break; + } + default:{ // MODE REMOTE MIRRORS + } + } + // error -> start downloading again +// msg_status2(segment->connection_num, toString(connection_result)+"]- Failed download "+segment->file_name); + debug(toString(connection_result)+"]- Failed download "+segment->url); + if (segment->try_num>=settings.max_tries){ + segment->status=SFAILED; + segment->parent_distfile->set_status(DFAILED); + error_log("Segget failed to download distfile: "+segment->parent_distfile->name); + error_log("Segment:"+segment->file_name+" has reached max_tries limit - segment.status set to FAILED"); + } + else segment->status=SWAITING; + }else{ + // no error => count this one and start new + log("Succesfully downloaded "+segment->file_name+" on connection#"+toString(connection_num)); + debug(" Successful download "+segment->url); +// already done earlier in this function Pcurr_mirror=find_mirror(strip_mirror_name(segment->url)); + segment->status=SDOWNLOADED; + segment->parent_distfile->inc_dld_segments_count(segment); + }; + if ((segment->parent_distfile->get_status()!=DFAILED) + and (segment->parent_distfile->get_status()!=DDOWNLOADED) + and (segment->parent_distfile->get_status()!=DALL_LM_AND_PF_MIRRORS_FAILED)){ + if (segment->parent_distfile->active_connections_num>0){ + segment->parent_distfile->set_status(DDOWNLOADING); + }else{ + segment->parent_distfile->set_status(DWAITING); + } + } + }catch(...){ + error_log("Error in connection.cpp: stop()"); + } +} + +void Tconnection::inc_bytes_per_last_interval(ulong new_bytes_count){ + try{ + total_dld_bytes+=new_bytes_count; + bytes_per_last_interval+=new_bytes_count; + }catch(...){ + error_log("Error in connection.cpp: inc_bytes_per_last_interval()"); + } +} + +void Tconnection::show_connection_progress(ulong time_diff){ + try{ + stats.total_bytes_per_last_interval+=bytes_per_last_interval; + ulong speed=(bytes_per_last_interval*1000)/time_diff; + ulong avg_speed=(total_dld_bytes*1000)/time_left_since(start_time); + string eta_string; + if (avg_speed==0){ + eta_string=" ETA: inf"; + }else{ + eta_string=" ETA: "+secsToString((segment->segment_size-segment->downloaded_bytes)/avg_speed); + } + string speed_str; + string avg_speed_str; + speed_str=" Speed: "+speedToString(speed); + avg_speed_str=" AVG speed: "+speedToString(avg_speed); + int percent=segment->downloaded_bytes*100/segment->segment_size; + string network_type_str; + switch (network_array[network_num].network_mode){ + case MODE_REMOTE: network_type_str="REM"; break; + case MODE_PROXY_FETCHER: network_type_str="P-F"; break; + case MODE_LOCAL: network_type_str="LOC"; break; + case MODE_CORAL_CDN: network_type_str="CDN"; break; + } + string progress_text=field("[Net",network_num,1) + +":"+network_type_str+"]" + +field(" Segment:",segment->segment_num, 5) + +field(" Try:",segment->try_num,4) + +field(" Bytes:",segment->downloaded_bytes,7) + +field(" / ",segment->segment_size,7) + +field(" = ",percent,3)+"%" + +speed_str + +avg_speed_str + +eta_string; + msg_segment_progress(segment->connection_num, progress_text); + bytes_per_last_interval=0; + }catch(...){ + error_log("Error in connection.cpp: show_connection_progress()"); + } +} + +string Tconnection::get_html_connection_progress(){ + try{ + ulong time_diff=time_left_since(stats.previous_time); +// stats.total_bytes_per_last_interval+=bytes_per_last_interval; + ulong speed=(bytes_per_last_interval*1000)/time_diff; + ulong avg_speed=(total_dld_bytes*1000)/time_left_since(start_time); + string eta_string; + if (avg_speed==0){ + eta_string="inf"; + }else{ + eta_string=secsToString((segment->segment_size-segment->downloaded_bytes)/avg_speed); + } + string speed_str; + string avg_speed_str; + speed_str=speedToString(speed); + avg_speed_str=speedToString(avg_speed); + int segment_percent; + if (segment->segment_size>0){ + segment_percent=segment->downloaded_bytes*100/segment->segment_size; + }else{ + segment_percent=100; + } + int distfile_percent; + if (segment->parent_distfile->size>0){ + distfile_percent=segment->parent_distfile->dld_bytes*100/segment->parent_distfile->size; + }else{ + distfile_percent=100; + } + + int unfinished_segments_distfile_percent; + //TO-DO: it's necessary to check all connections and add dld bytes to be correct !!! + if (segment->parent_distfile->size>0){ + unfinished_segments_distfile_percent=segment->downloaded_bytes*100/segment->parent_distfile->size; + }else{ + unfinished_segments_distfile_percent=0; + } + string network_type_str; + switch (network_array[network_num].network_mode){ + case MODE_REMOTE: network_type_str="Remote"; break; + case MODE_PROXY_FETCHER: network_type_str="Proxy-Fetcher"; break; + case MODE_LOCAL: network_type_str="Local"; break; + case MODE_CORAL_CDN: network_type_str="CDN"; break; + } + string progress_text= + (string)"<td align=\"center\">\n<table width=\"100\" border=\"0\" cellpadding=\"0\" frame=\"void\">\n<tr>\n" + +((distfile_percent>0)?"<td bgcolor=\"#0000FF\">\n<img src=\"/img/blue_progress.jpg\" height=\"20\" width=\""+toString(distfile_percent)+"\"/>\n</td>\n" + :"") + +((unfinished_segments_distfile_percent>0)?"<td bgcolor=\"#00FF00\">\n<img src=\"/img/green_progress.jpg\" height=\"20\" width=\""+toString(unfinished_segments_distfile_percent)+"\"/>\n</td>\n" + :"") + +((100-distfile_percent-unfinished_segments_distfile_percent>0)?"<td bgcolor=\"#555555\">\n<img src=\"/img/bw_progress.jpg\" height=\"20\" width=\""+toString(100-distfile_percent-unfinished_segments_distfile_percent)+"\" />\n</td>\n" + :"") + +"</tr>\n</table>\n" +// +" "+toString(distfile_percent+unfinished_segments_distfile_percent)+"%" + +toString(distfile_percent)+"%" + +"</td>\n<td>\n" + +"<table>\n" + +"<tr>\n<td>"+segment->parent_distfile->name+"</td>\n</tr>\n" + +"<tr>\n<td>\n"+segment->url+"</td>\n</tr>\n" + +"</table>\n" + +"</td><td align=\"center\"><table width=\"100\" border=\"0\" cellpadding=\"0\" frame=\"void\"><tr>" + +((segment_percent>0)?"<td bgcolor=\"#00FF00\"><img src=\"/img/green_progress.jpg\" height=\"20\" width=\""+toString(segment_percent)+"\"/></td>" + :"") + +((100-segment_percent>0)?"<td bgcolor=\"#555555\"><img src=\"/img/bw_progress.jpg\" height=\"20\" width=\""+toString(100-segment_percent)+"\" /></td>" + :"") + +"</tr></table>" + +toString(segment_percent)+"%" + +"</td><td align=\"right\">"+toString(segment->segment_num) + +"</td><td align=\"right\">"+toString(segment->try_num) + +"</td><td align=\"right\">"+toString(network_num) + +"</td><td align=\"center\">"+network_type_str + +"</td><td align=\"right\">"+toString(segment->downloaded_bytes) + +"</td><td align=\"right\">"+toString(segment->segment_size) + +"</td><td align=\"right\">"+speed_str + +"</td><td align=\"right\">"+avg_speed_str + +"</td><td align=\"right\">"+eta_string + +"</td>"; + return progress_text; + }catch(...){ + error_log("Error in connection.cpp: show_connection_progress()"); + } + return ""; +}
\ No newline at end of file |