2009-08-04 16 views
8

मैं थ्रेडेड एफ़टीपी कनेक्शन का उपयोग कर कई एफ़टीपी डाउनलोड को तेज करने की कोशिश कर रहा था। मेरी समस्या यह है कि मेरे पास हमेशा धागे लटकते हैं। मैं या तो एफ़टीपी को कहने का एक साफ तरीका ढूंढ रहा हूं कि इसे FTP लेनदेन को फिर से प्रयास करने की आवश्यकता है, या कम से कम यह जानना कि एफ़टीपी कनेक्शन लटक रहा है।रूबी नेट :: एफ़टीपी टाइमआउट थ्रेड

कोड में नीचे मैं 5/6 अलग एफ़टीपी कनेक्शन जहां प्रत्येक धागा फ़ाइलों इसे डाउनलोड करने की उम्मीद है की एक सूची है सूत्रण कर रहा हूँ। जब स्क्रिप्ट पूर्ण हो जाती है, तो कुछ धागे लटकते हैं और इसमें शामिल नहीं हो सकते हैं। मैं अंतिम सफल डाउनलोड समय का प्रतिनिधित्व करने के लिए वेरिएबल @last_updated का उपयोग कर रहा हूं। यदि वर्तमान समय + 20 सेकंड @last_updated से अधिक है, तो शेष धागे को मार दें। क्या कोई बेहतर तरीका है?

threads = [] 
max_thread_pool = 5 
running_threads = 0 
Thread.abort_on_exception = true 

existing_file_count = 0 
files_downloaded = 0 

errors = [] 
missing_on_the_server = [] 
@last_updated = Time.now 

if ids.length > 0 
    ids.each_slice(ids.length/max_thread_pool) do |id_set| 
     threads << Thread.new(id_set) do |t_id_set| 
      running_threads += 1 
      thread_num = running_threads 
      thread_num.freeze 
      puts "making thread # #{thread_num}" 
      begin 
       ftp = Net::FTP.open(@remote_site) 
       ftp.login(@remote_user, @remote_password) 
       ftp.binary = true 
       #ftp.debug_mode = true 
       ftp.passive = false 
      rescue 
       raise "Could not establish FTP connection" 
      end 
      t_id_set.each do |id| 
       @last_updated = Time.now 
       rmls_path = "/_Photos/0#{id[0,2]}00000/#{id[2,1]}0000/#{id[3,1]}000/#{id}-1.jpg" 
       local_path = "#{@photos_path}/01/#{id}-1.jpg" 
       progress += 1 
       unless File.exist?(local_path) 
        begin 
         ftp.getbinaryfile(rmls_path, local_path) 
         puts "ftp reponse: #{ftp.last_response}" 
         # find the percentage of progress just for fun 
         files_downloaded += 1 
         p = sprintf("%.2f", ((progress.to_f/total) * 100)) 
         puts "Thread # #{thread_num} > %#{p} > #{progress}/#{total} > Got file: #{local_path}" 
        rescue 
         errors << "#{thread_num} unable to get file > ftp response: #{ftp.last_response}" 
         puts errors.last 
         if ftp.last_response_code.to_i == 550 
          # Add the missing file to the missing list 
          missing_on_the_server << errors.last.match(/\d{5,}-\d{1,2}\.jpg/)[0] 
         end 
        end 
       else 
        puts "found file: #{local_path}" 
        existing_file_count += 1 
       end 
      end 
      puts "closing FTP connection #{thread_num}" 
      ftp.close 
     end # close thread 
    end 
end 

# If @last_updated has not been updated on the server in over 20 seconds, wait 3 seconds and check again 
while Time.now < @last_updated + 20 do 
    sleep 3 
end 
# threads are hanging so joining the threads does not work. 
threads.each { |t| t.kill } 

उत्तर

9

मेरे लिए चाल है कि काम किया माणिक के Timeout.timeout उपयोग करने के लिए सुनिश्चित करने के लिए FTP कनेक्शन फांसी नहीं किया गया था।

begin 
    Timeout.timeout(10) do 
     ftp.getbinaryfile(rmls_path, local_path) 
    end 
    # ... 
rescue Timeout::Error 
    errors << "#{thread_num}> File download timed out for: #{rmls_path}" 
    puts errors.last 
rescue 
    errors << "unable to get file > ftp reponse: #{ftp.last_response}" 
    # ... 
end 

एफ़टीपी डाउनलोड लटकाने से मेरे धागे लटकने लगते थे। बल्कि बदसूरत से

threads.each { |t| j.join } 

: अब जब कि धागे लंबे समय तक फांसी नहीं कर रहे हैं, मैं और अधिक उचित तरीके से धागे से निपटने का उपयोग कर सकते हैं

# If @last_updated has not been updated on the server in over 20 seconds, wait 3 seconds and check again 
while Time.now < @last_updated + 20 do 
    sleep 3 
end 
# threads are hanging so joining the threads does not work. 
threads.each { |t| t.kill } 
संबंधित मुद्दे