1 | #!/bin/env perl |
---|
2 | |
---|
3 | use strict; |
---|
4 | use warnings; |
---|
5 | use Getopt::Long; |
---|
6 | use Sophie::Scan; |
---|
7 | use Sophie::Base; |
---|
8 | use Sys::Syslog; |
---|
9 | use Pod::Usage; |
---|
10 | |
---|
11 | GetOptions( |
---|
12 | 'd|daemon' => \my $daemon, |
---|
13 | 'sleep=i' => \my $sleep, |
---|
14 | 'runas=s' => \my $runas, |
---|
15 | 'pidfile=s' => \my $pidfile, |
---|
16 | ) or do { pod2usage(1) }; |
---|
17 | |
---|
18 | $ENV{LC_ALL} = 'C'; |
---|
19 | require Sophie::Scan::RpmsPath; |
---|
20 | |
---|
21 | sub process_rpms { |
---|
22 | my $scan = Sophie::Scan->new; |
---|
23 | $scan->update_meta_paths; |
---|
24 | |
---|
25 | my @pkey = $scan->list_unscanned_paths; |
---|
26 | |
---|
27 | foreach my $pathkey (@pkey) { |
---|
28 | |
---|
29 | my $time = time; |
---|
30 | my $mark = 0; |
---|
31 | my @delta; |
---|
32 | |
---|
33 | { |
---|
34 | my $path = Sophie::Scan::RpmsPath |
---|
35 | ->new($pathkey, Sophie::Scan->new); |
---|
36 | |
---|
37 | $mark = $path->get_needupdate; |
---|
38 | @delta = $path->find_delta; |
---|
39 | } |
---|
40 | |
---|
41 | while (my @d = splice(@delta, 0, 10)) { |
---|
42 | my $scan = Sophie::Scan->new; |
---|
43 | my $path = Sophie::Scan::RpmsPath->new($pathkey, $scan); |
---|
44 | $path->update_content(@d); |
---|
45 | last if (time > $time + 7 * 60); |
---|
46 | } |
---|
47 | |
---|
48 | if (!@delta) { # update only if we finished |
---|
49 | my $path = Sophie::Scan::RpmsPath->new($pathkey, Sophie::Scan->new); |
---|
50 | $path->set_updated; |
---|
51 | $path->set_no_needupdate |
---|
52 | unless ($mark ne $path->get_needupdate); |
---|
53 | } |
---|
54 | } |
---|
55 | } |
---|
56 | |
---|
57 | sub process_maint { |
---|
58 | my $sophie = Sophie::Base->connect; |
---|
59 | |
---|
60 | foreach my $maintsource ( |
---|
61 | $sophie->resultset('MaintSources') |
---|
62 | ->search->all) { |
---|
63 | |
---|
64 | my $realclass = 'Sophie::Maint::' . $maintsource->accessor; |
---|
65 | no strict qw(refs); |
---|
66 | eval "require $realclass;"; |
---|
67 | next if($@); |
---|
68 | |
---|
69 | warn "Updating maintainers for " . $maintsource->label . "\n"; |
---|
70 | my $fetcher = $realclass->new($maintsource); |
---|
71 | if (my $list = $fetcher->fetch) { |
---|
72 | $sophie->resultset('MaintRpm')->search( |
---|
73 | { |
---|
74 | sources => $maintsource->pkey, |
---|
75 | } |
---|
76 | )->delete; |
---|
77 | |
---|
78 | foreach (@$list) { |
---|
79 | $_->{sources} = $maintsource->pkey; |
---|
80 | } |
---|
81 | |
---|
82 | $sophie->txn_do( |
---|
83 | sub { |
---|
84 | $sophie->resultset('MaintRpm')->populate($list) && |
---|
85 | $maintsource->update({ lastupdated => 'now()' }); |
---|
86 | } |
---|
87 | ); |
---|
88 | } |
---|
89 | } |
---|
90 | } |
---|
91 | |
---|
92 | openlog('sophie-update', 'ndelay,pid' . ($daemon ? '' : ',perror'), 'user'); |
---|
93 | $SIG{__WARN__} = sub { |
---|
94 | syslog('warning', @_); |
---|
95 | }; |
---|
96 | $SIG{__DIE__} = sub { |
---|
97 | syslog('crit', @_); |
---|
98 | exit(1); |
---|
99 | }; |
---|
100 | |
---|
101 | if ($daemon) { |
---|
102 | if (fork()) { |
---|
103 | exit(0); |
---|
104 | } |
---|
105 | warn "Fork done, entering daemon mode\n"; |
---|
106 | } |
---|
107 | |
---|
108 | if ($pidfile) { |
---|
109 | if (open(my $handle, '>', $pidfile)) { |
---|
110 | print $handle $$ . "\n"; |
---|
111 | close($handle); |
---|
112 | } else { |
---|
113 | die "Can't write pidfile $pidfile, exiting :\\\n"; |
---|
114 | } |
---|
115 | } |
---|
116 | |
---|
117 | |
---|
118 | if ($runas) { |
---|
119 | my ($login,$pass,$uid,$gid) = $runas =~ /^\d/ |
---|
120 | ? getpwuid($runas) |
---|
121 | : getpwnam($runas); |
---|
122 | |
---|
123 | $> = $uid; $) = $gid; |
---|
124 | if ($> ne $uid) { |
---|
125 | die "Cannot change to user $runas\n"; |
---|
126 | } |
---|
127 | } |
---|
128 | |
---|
129 | $sleep ||= 60; |
---|
130 | |
---|
131 | my $lastmaint = 0; |
---|
132 | |
---|
133 | while (1) { |
---|
134 | my $csleep = int(rand($sleep) + ($sleep / 2 )); |
---|
135 | my $currenttime = time; |
---|
136 | if (my $pid = fork) { |
---|
137 | waitpid($pid, 0); |
---|
138 | } else { |
---|
139 | process_rpms(); |
---|
140 | exit(0); |
---|
141 | } |
---|
142 | |
---|
143 | if ($lastmaint < time - ($sleep * 100)) { |
---|
144 | if (my $pid = fork) { |
---|
145 | waitpid($pid, 0); |
---|
146 | $lastmaint = time; |
---|
147 | } else { |
---|
148 | process_maint(); |
---|
149 | exit(0); |
---|
150 | } |
---|
151 | } |
---|
152 | |
---|
153 | my $delay = $csleep - (time - $currenttime); |
---|
154 | |
---|
155 | if ($delay > 0) { |
---|
156 | warn "sleep $delay\n"; |
---|
157 | sleep $delay; |
---|
158 | } |
---|
159 | } |
---|