summaryrefslogtreecommitdiffstats
path: root/perl-install/mirror.pm
blob: b61f24066d2f20185219fe023edfb263a38cea51 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package mirror; # $Id$

use diagnostics;
use strict;
use feature 'state';

use common;
use log;

my %land2tzs = (
	     N_("Australia") => [ 'Australia/Sydney' ],
	     N_("Austria") => [ 'Europe/Vienna', 'Europe/Brussels', 'Europe/Berlin' ],
	     N_("Belgium") => [ 'Europe/Brussels', 'Europe/Paris', 'Europe/Berlin' ],
	     N_("Brazil") => [ 'Brazil/East' ],
	     N_("Canada") => [ 'Canada/Atlantic', 'Canada/Eastern' ],
	     N_("Costa Rica") => [ 'America/Costa_Rica' ],
	     N_("Czech Republic") => [ 'Europe/Prague', 'Europe/Berlin' ],
	     N_("Denmark") => [ 'Europe/Copenhagen', 'Europe/Berlin' ],
	     N_("Estonia") => [ 'Europe/Tallinn', 'Europe/Helsinki' ],
	     N_("Finland") => [ 'Europe/Helsinki', 'Europe/Tallinn' ],
	     N_("France") => [ 'Europe/Paris', 'Europe/Brussels', 'Europe/Berlin' ],
	     N_("Germany") => [ 'Europe/Berlin', 'Europe/Prague' ],
	     N_("Greece") => [ 'Europe/Athens', 'Europe/Prague' ],
	     N_("Hungary") => [ 'Europe/Budapest' ],
	     N_("Ireland") => [ 'Europe/Dublin', 'Europe/London' ],
	     N_("Israel") => [ 'Asia/Tel_Aviv' ],
	     N_("Italy") => [ 'Europe/Rome', 'Europe/Brussels', 'Europe/Paris' ],
	     N_("Japan") => [ 'Asia/Tokyo', 'Asia/Seoul' ],
	     N_("Netherlands") => [ 'Europe/Amsterdam', 'Europe/Brussels', 'Europe/Berlin' ],
	     N_("New Zealand") => [ 'Pacific/Auckland' ],
	     N_("Norway") => [ 'Europe/Oslo', 'Europe/Stockholm' ],
	     N_("Poland") => [ 'Europe/Warsaw' ],
	     N_("Portugal") => [ 'Europe/Lisbon', 'Europe/Madrid' ],
	     N_("Russia") => [ 'Europe/Moscow', ],
	     N_("Slovakia") => [ 'Europe/Bratislava' ],
	     N_("South Africa") => [ 'Africa/Johannesburg' ],
	     N_("Spain") => [ 'Europe/Madrid', 'Europe/Lisbon' ],
	     N_("Sweden") => [ 'Europe/Stockholm', 'Europe/Oslo' ],
	     N_("Switzerland") => [ 'Europe/Zurich', 'Europe/Berlin', 'Europe/Brussels' ],
	     N_("Taiwan") => [ 'Asia/Taipei', 'Asia/Seoul' ],
	     N_("Thailand") => [ 'Asia/Bangkok', 'Asia/Seoul' ],
	     N_("United States") => [ 'America/New_York', 'Canada/Atlantic', 'Asia/Tokyo', 'Australia/Sydney', 'Europe/Paris' ],
	    );

sub mirror2text {
    my ($mirror) = @_;
    translate($mirror->{country})  . '|' . $mirror->{host} . ($mirror->{method} ? " ($mirror->{method})" : '');
}

my $downloader;
sub register_downloader {
    my ($func) = @_;
    $downloader = $func;
}

sub mirrors_raw {
    my ($product_id, $o_arch) = @_;

    #- contact the following URL to retrieve the list of mirrors.
    #- http://wiki.mandriva.com/en/Product_id
    my $type = lc($product_id->{type}); $type =~ s/\s//g;
    local $product_id->{arch} = $o_arch if $o_arch;
    my $list = "http://api.mandriva.com/mirrors/$type.$product_id->{version}.$product_id->{arch}.list";
    log::explanations("trying mirror list from $list");
    my @lines;
    if ($::isInstall) {
        require install::http;
        my $f = install::http::getFile($list) or die "mirror list not found";
        local $SIG{ALRM} = sub { die "timeout" };
        alarm 60;
        log::l("using mirror list $list");
        push @lines, $_ while <$f>;
        install::http::close();
        alarm 0; 
    } else {
        if (ref($downloader)) {
            @lines = $downloader->($list);
            @lines or die "mirror list not found";
        } else {
            die "Missing download callback";
        }
    }
    map { common::parse_LDAP_namespace_structure(chomp_($_)) } @lines;
}

sub list {
    my ($product_id, $type, $o_arch) = @_;

    our @mirrors_raw;
    state $prev_arch;
    undef @mirrors_raw if $prev_arch ne $o_arch;
    $prev_arch = $o_arch || arch();
    if (!@mirrors_raw) {
        @mirrors_raw = eval { mirrors_raw($product_id, $o_arch) };
        if (my $err = $@) {
            log::explanations("failed to download mirror list");
            die $err;
        }
        @mirrors_raw or log::explanations("empty mirror list"), return;
    }

	my @mirrors = grep {
	    ($_->{method}, $_->{host}, $_->{dir}) = $_->{url} =~ m!^(ftp|http)://(.*?)(/.*)!;
	    $_->{method} && ($type eq 'all' || $_->{type} eq $type);
	} @mirrors_raw or log::explanations("no mirrors of type $type"), return;

    @mirrors && \@mirrors;
}

sub nearest {
    my ($timezone, $mirrors) = @_;

    my (@country, @zone);
    foreach my $mirror (@$mirrors) {
	my @tzs = @{$land2tzs{$mirror->{country}} || []};
	eval { push @{$country[find_index { $_ eq $timezone } @tzs]}, $mirror };
	eval { push @{$zone[find_index { ((split '/')[0] eq (split '/', $timezone)[0]) } @tzs]}, $mirror };
    }
    my @l = @country ? @country : @zone;
    shift @l while !$l[0] && @l;
    
    my @possible = @l ? ((@{$l[0]}) x 2, @{$l[1] || []}) : @$mirrors;
    $possible[rand @possible];
}

1;