File Coverage

blib/lib/App/cdnget.pm
Criterion Covered Total %
statement 30 36 83.3
branch 1 2 50.0
condition n/a
subroutine 10 10 100.0
pod n/a
total 41 48 85.4


line stmt bran cond sub pod time code
1             package App::cdnget;
2             =head1 NAME
3              
4             App::cdnget - CDN Reverse Proxy
5              
6             =head1 VERSION
7              
8             version 0.04
9              
10             =head1 ABSTRACT
11              
12             CDN Reverse Proxy
13              
14             =head1 DESCRIPTION
15              
16             p5-cdnget is a FastCGI application that flexible pull-mode Content Delivery Network reverse proxy.
17              
18             B<This is ALPHA version>
19              
20             =cut
21             BEGIN
22             {
23 2     2   109152 require Config;
24 2 50       22 if ($Config::Config{'useithreads'})
25             {
26 0         0 require threads;
27 0         0 threads->import();
28 0         0 require threads::shared;
29 0         0 threads::shared->import();
30             } else
31             {
32 2         1920 require forks;
33 1         207086 forks->import();
34 1         73 require forks::shared;
35 1         7 forks::shared->import();
36             }
37             }
38 1     1   98 use strict;
  1         5  
  1         18  
39 1     1   3 use warnings;
  1         1  
  1         17  
40 1     1   7 use v5.14;
  1         5  
41 1     1   526 use utf8;
  1         8  
  1         58  
42 1     1   30 use Time::HiRes qw(sleep usleep);
  1         1  
  1         14  
43 1     1   1014 use DateTime;
  1         331953  
  1         47  
44 1     1   621 use Lazy::Utils;
  1         43905  
  1         28  
45              
46 1     1   585 use App::cdnget::Exception;
  1         3  
  1         20  
47 1     1   456 use App::cdnget::Worker;
  0            
  0            
48             use App::cdnget::Downloader;
49              
50              
51             BEGIN
52             {
53             require Exporter;
54             our $VERSION = '0.04';
55             our @ISA = qw(Exporter);
56             our @EXPORT = qw(main run);
57             our @EXPORT_OK = qw();
58             }
59              
60              
61             our $DTF_RFC822 = "%a, %d %b %Y %T %Z";
62             our $DTF_RFC822_GMT = "%a, %d %b %Y %T GMT";
63             our $DTF_YMDHMS = "%F %T";
64             our $DTF_YMDHMS_Z = "%F %T %z";
65             our $DTF_SYSLOG = "%b %e %T";
66             our $CHUNK_SIZE = 256*1024;
67              
68             my $terminating :shared = 0;
69             my $terminating_force :shared = 0;
70              
71              
72             sub log_info
73             {
74             my ($msg) = @_;
75             $msg = "Unknown" unless $msg;
76             my $dts = DateTime->now(time_zone => POSIX::strftime("%z", localtime), locale => "en")->strftime('%x %T %z');
77             $msg = "[$dts] $msg";
78             say $msg;
79             }
80              
81             sub main
82             {
83             log_info "Starting p5-cdnget/${App::cdnget::VERSION}";
84             eval
85             {
86             my $cmdargs = commandArgs({ valuableArgs => 1, noCommand => 1 }, @_);
87             my $spares = $cmdargs->{"--spares"};
88             $spares = 1 unless defined($spares) and $spares >= 1;
89             my $maxWorkers = $cmdargs->{"--max-workers"};
90             $maxWorkers = $spares+1 unless defined($maxWorkers) and $maxWorkers > $spares;
91             my $cachePath = $cmdargs->{"--cache-path"};
92             $cachePath = "/tmp/cdnget" unless defined($cachePath);
93             my $addr = $cmdargs->{"--addr"};
94             $addr = "" unless defined($addr);
95             App::cdnget::Worker::init($spares, $maxWorkers, $cachePath, $addr);
96             App::cdnget::Downloader::init($maxWorkers*10);
97             $SIG{INT} = $SIG{TERM} = sub
98             {
99             terminate();
100             };
101             log_info "Started ".
102             "spares=$spares ".
103             "max-workers=$maxWorkers ".
104             "cache-path=\"".shellmeta($cachePath)."\" ".
105             "addr=\"".shellmeta($addr)."\"";
106             while (not App::cdnget::Worker::terminated() or not App::cdnget::Downloader::terminated())
107             {
108             eval { App::cdnget::Worker->new() };
109             warn $@ if $@;
110             }
111             App::cdnget::Worker::final();
112             App::cdnget::Downloader::final();
113             };
114             if ($@)
115             {
116             warn $@;
117             }
118             usleep(100*1000);
119             log_info "Terminated p5-cdnget/${App::cdnget::VERSION}";
120             return 0;
121             }
122              
123             sub run
124             {
125             return main(@ARGV);
126             }
127              
128             sub terminate
129             {
130             do
131             {
132             lock($terminating);
133             if ($terminating)
134             {
135             log_info "Terminating...";
136             lock($terminating_force);
137             $terminating_force = 1;
138             return 0;
139             }
140             $terminating = 1;
141             };
142             log_info "Terminating gracefully...";
143             async { App::cdnget::Worker::terminate() }->detach();
144             async { App::cdnget::Downloader::terminate() }->detach();
145             return 1;
146             }
147              
148              
149             1;
150             __END__
151             =head1 INSTALLATION
152              
153             To install this module type the following
154              
155             perl Makefile.PL
156             make
157             make test
158             make install
159              
160             from CPAN
161              
162             cpan -i App::cdnget
163              
164             =head1 DEPENDENCIES
165              
166             This module requires these other modules and libraries:
167              
168             =over
169              
170             =item *
171              
172             threads
173              
174             =item *
175              
176             threads::shared
177              
178             =item *
179              
180             forks
181              
182             =item *
183              
184             SUPER
185              
186             =item *
187              
188             Thread::Semaphore
189              
190             =item *
191              
192             Time::HiRes
193              
194             =item *
195              
196             DateTime
197              
198             =item *
199              
200             FCGI
201              
202             =item *
203              
204             Digest::SHA
205              
206             =item *
207              
208             LWP::UserAgent
209              
210             =item *
211              
212             GD
213              
214             =item *
215              
216             Lazy::Utils
217              
218             =item *
219              
220             Object::Base
221              
222             =back
223              
224             =head1 REPOSITORY
225              
226             B<GitHub> L<https://github.com/orkunkaraduman/p5-cdnget>
227              
228             B<CPAN> L<https://metacpan.org/release/App-cdnget>
229              
230             =head1 AUTHOR
231              
232             Orkun Karaduman <orkunkaraduman@gmail.com>
233              
234             =head1 COPYRIGHT AND LICENSE
235              
236             Copyright (C) 2017 Orkun Karaduman <orkunkaraduman@gmail.com>
237              
238             This program is free software: you can redistribute it and/or modify
239             it under the terms of the GNU General Public License as published by
240             the Free Software Foundation, either version 3 of the License, or
241             (at your option) any later version.
242              
243             This program is distributed in the hope that it will be useful,
244             but WITHOUT ANY WARRANTY; without even the implied warranty of
245             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
246             GNU General Public License for more details.
247              
248             You should have received a copy of the GNU General Public License
249             along with this program. If not, see <http://www.gnu.org/licenses/>.
250              
251             =cut