#!/usr/bin/ruby require 'date' require 'net/http' require 'optparse' require 'thread' require 'uri' def get_dates(base, archs_per_distro, optional=true) r = {} archs_per_distro.each{|d, archs| r[d] = {} archs.each{|a| begin r[d][a] = get_date(base, d, a) rescue Net::OpenTimeout, Timeout::Error, ArgumentError, NoMethodError, Errno::EHOSTUNREACH, Errno::ECONNREFUSED => e if !optional then STDERR.puts "Failed to fetch #{version_url(url, distrib, arch)}" raise end end } } r end def get_mirrors # TODO Get it from the DB mirrors = [] fetch_url("http://mirrors.mageia.org/").each_line{|l| next unless l =~ /http:.*>http/ mirrors << l.sub(/ 'check_mirrors'}) case response when Net::HTTPSuccess then return response.body when Net::HTTPRedirection then location = response['location'] # Make location absolute if it was not if location =~ /:\/\// then fetch_url(location, redirect_limit - 1) else uri.path = location fetch_url(uri.to_s, redirect_limit - 1) end end end end def parse_version(version) date = version.sub(/.* (........ ..:..)$/, '\1').rstrip DateTime.strptime(date, '%Y%m%d %H:%M') end def version_url(url, distrib, arch) "#{url}/distrib/#{distrib}/#{arch}/VERSION" end def get_date(url, distrib, arch) return parse_version(fetch_url(version_url(url, distrib, arch))) end def print_output(archs_per_distro, mirrors, ref_times, times) puts " " puts "Last checked on #{Time.now.strftime("%F %R")}
" puts "
Up to dateLess than 12h oldLess than 2 days oldOld or broken
" puts "" puts "" } puts "" puts "" } } puts "" puts "" puts "" archs_per_distro.each{|d, archs| puts " " } } puts "" mirrors.each{|u| puts "" archs_per_distro.each{|d, archs| puts " " else puts " " end else puts " " end } } puts "" } puts "
" archs_per_distro.each{|d, archs| nb_arches = archs.size puts " #{d}
" archs_per_distro.each{|d, archs| puts " " archs.each{|a| puts " #{a}
Reference" archs.each{|a| puts " #{ref_times[d][a].strftime("%F %R")}
#{u}" archs.each{|a| if times[u][d][a] != nil then cls = 'broken' diff = ref_times[d][a] - times[u][d][a] if diff == 0 then cls = 'ok' elsif diff < 0.5 then cls = 'almost' elsif diff < 2 then cls = 'bad' end if cls == 'ok' then puts "  #{times[u][d][a].strftime("%F %R")}X
" puts "" end # Defaults ref = 'http://repository.mageia.org/' archs_per_distro = { '6' => ['i586', 'x86_64', 'armv5tl', 'armv7hl'], '7' => ['i586', 'x86_64', 'armv7hl', 'aarch64'], 'cauldron' => ['i586', 'x86_64', 'armv7hl', 'aarch64'] } parallel = 8 OptionParser.new {|opts| opts.banner = "Usage: #{$0} [options]" opts.on("--repository URL", "Reference repository. Default: #{ref}") { |url| ref = url } opts.on("--parallel n", Integer, "Max number of parallel connections. Default: #{parallel}") { |n| $parallel = n } opts.on("--output file", "Write output into given file. Default to STDOUT") { |f| $stdout.reopen(f, "w") } }.parse! # Get dates from the reference repository, and fail if some requested distros # or archs are missing ref_times = get_dates(ref, archs_per_distro, false) # Get the list of mirror URLs to check mirrors = get_mirrors workqueue = Queue.new times = {} # Create all the thread and have them loop on the work queue threads = (1..parallel).map{|n| Thread.new { loop do u = workqueue.pop break if u == :exit times[u] = get_dates(u, archs_per_distro) end } } # Push all mirrors into the queue mirrors.each{|u| workqueue << u } # Get all the threads to exit after all the work is done parallel.times{|i| workqueue << :exit } # Wait for the threads to exit threads.each{|t| t.join } # Generate output print_output(archs_per_distro, mirrors, ref_times, times)