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