File Coverage

blib/lib/Schedule/Load/Schedule.pm
Criterion Covered Total %
statement 130 151 86.0
branch 39 84 46.4
condition 12 42 28.5
subroutine 22 25 88.0
pod 10 14 71.4
total 213 316 67.4


line stmt bran cond sub pod time code
1             # Schedule::Load::Schedule.pm -- Schedule jobs across a network
2             # See copyright, etc in below POD section.
3             ######################################################################
4              
5             package Schedule::Load::Schedule;
6             require 5.004;
7             require Exporter;
8             @ISA = qw(Exporter Schedule::Load::Hosts);
9              
10 1     1   102853 use Schedule::Load qw (:_utils);
  1         4  
  1         174  
11 1     1   721 use Schedule::Load::Hosts;
  1         3  
  1         61  
12 1     1   633 use Schedule::Load::ResourceReq;
  1         3  
  1         30  
13 1     1   5 use Sys::Hostname;
  1         3  
  1         41  
14 1     1   6 use Time::localtime;
  1         1  
  1         54  
15              
16 1     1   5 use strict;
  1         2  
  1         28  
17 1     1   58 use vars qw($VERSION $Debug @MoY);
  1         2  
  1         52  
18 1     1   5 use Carp;
  1         2  
  1         1719  
19              
20             ######################################################################
21             #### Configuration Section
22              
23             # Other configurable settings.
24             $Debug = $Schedule::Load::Debug;
25             $VERSION = '3.064';
26             @MoY = ('Jan','Feb','Mar','Apr','May','Jun',
27             'Jul','Aug','Sep','Oct','Nov','Dec');
28              
29             ######################################################################
30             #### Globals
31              
32             ######################################################################
33             #### Creator
34              
35             sub new {
36 1 50   1 0 560 @_ >= 1 or croak 'usage: '.__PACKAGE__.'->new ({options})';
37 1         10 my $proto = shift;
38 1         72 return $proto->SUPER::new
39             ( scheduled_hosts => [],
40             @_);
41             }
42              
43             ######################################################################
44             #### Constructor
45              
46             ######################################################################
47             #### Accessors
48              
49             sub scheduled_hosts {
50 8 50 33 8 1 11 my $self = shift; ($self && ref($self)) or croak 'usage: $self->scheduled_hosts (perhaps you forgot to check schedule return for undef)';
  8         43  
51 8 100       32 return (wantarray ? @{$self->{scheduled_hosts}} : $self->{scheduled_hosts});
  4         18  
52             }
53              
54             sub scheduled_hostnames {
55 4 50 33 4 0 9 my $self = shift; ($self && ref($self)) or croak 'usage: $self->scheduled_hosts (perhaps you forgot to check schedule return for undef)';
  4         30  
56 4 50       15 return () if !$self->{scheduled_hosts}[0];
57 4         14 my @names = map {$_->hostname; } $self->scheduled_hosts;
  4         216  
58 4         16 return @names;
59             }
60              
61             sub hosts_of_class {
62 0 0 0 0 1 0 my $self = shift; ($self && ref($self)) or croak 'usage: $self->hosts()';
  0         0  
63             # DEPRECIATED. Return all hosts matching given class
64             # allow_reserved was ignored in the old implementation...
65 0         0 return $self->hosts_match (@_, allow_reserved=>1);
66             }
67              
68             ######################################################################
69             ######################################################################
70             #### Functions
71              
72             sub reserve_default_comment {
73 1 50 33 1 0 10 my $self = shift; ($self && ref($self)) or croak 'usage: $self->reserve_default_comment)';
  1         19  
74 1         10 return sprintf ("$self->{username} at %02d-%s %02d:%02d",
75             localtime->mday, $MoY[localtime->mon],
76             localtime->hour, localtime->min),
77             }
78              
79             sub reserve {
80 1 50 33 1 1 441 my $self = shift; ($self && ref($self)) or croak 'usage: $self->reserve)';
  1         22  
81 1         9 my $params = {
82             host=>hostname(),
83             uid=>$<,
84             comment=>$self->reserve_default_comment(),
85             @_,};
86              
87 1 50       738 print __PACKAGE__."::reserve($params->{host}, $params->{comment})\n" if $Debug;
88 1         5 $self->_fetch_if_unfetched();
89              
90 1         6 my $host = $self->get_host($params->{host});
91 1 50       6 ($host) or die "%Error: Host $params->{host} not found, so not reserved\n";
92 1 50       492 (!$host->reserved) or die "%Error: Host $params->{host} already reserved by ".$host->reserved."\nrelease this reservation first.\n";
93 1 50       30 ($host->reservable) or die "%Error: Host $params->{host} is not reservable\n";
94              
95 1         8 $self->set_stored(host=>$params->{host},
96             reserved=>$params->{comment},);
97 1         8 $self->fetch();
98 1         23 $host = $self->get_host($params->{host}); # Fetch might have new reference
99 1 50       15 ($host) or croak "%Error: Host $params->{host} not responding";
100 1 50       45 ($host->reserved) or croak "%Error: Host $params->{host} didn't accept reservation";
101             }
102              
103             sub release {
104 1 50 33 1 1 7 my $self = shift; ($self && ref($self)) or croak 'usage: $self->hosts)';
  1         25  
105 1         8 my $params = {
106             host=>hostname(),
107             @_,};
108              
109 1 50       10 print __PACKAGE__."::release($params->{host})\n" if $Debug;
110 1         5 $self->_fetch_if_unfetched();
111              
112 1         4 my $host = $self->get_host($params->{host});
113 1 50       5 if (!$host) {
114 0         0 warn "Note: Host $params->{host} not found, so not released\n";
115 0         0 return;
116             }
117 1 50       22 if (!$host->reserved) {
118 0         0 warn "Note: Host $params->{host} not reserved, so not released\n";
119 0         0 return;
120             }
121              
122 1         6 $self->set_stored(host=>$params->{host},
123             reserved=>0,);
124 1         7 $self->fetch();
125 1         8 $host = $self->get_host($params->{host}); # Fetch might have new reference
126 1 50       21 ($host) or croak "%Error: Host $params->{host} not responding";
127 1 50       56 (!$host->reserved) or croak "%Error: Host $params->{host} didn't accept release";
128             }
129              
130             sub fixed_load {
131 1 50 33 1 1 765 my $self = shift; ($self && ref($self)) or croak 'usage: $self->fixed_load)';
  1         20  
132 1         9 my $params = {
133             host=>hostname(),
134             load=>1, # Negative for all cpus
135             uid=>$<,
136             pid=>$$,
137             req_hostname=>hostname(), # Where to do a pid_exists
138             #req_pid=>pid,
139             @_,};
140 1   33     55 $params->{req_pid} ||= $params->{pid};
141 1 50       4 print __PACKAGE__."::fixed_load($params->{load})\n" if $Debug;
142 1         5 $self->_request(_pfreeze( 'report_fwd_fixed_load', $params, $Debug));
143             }
144              
145             sub hold_release {
146 4 50 33 4 1 908 my $self = shift; ($self && ref($self)) or croak 'usage: $self->hold_release)';
  4         42  
147 4         37 my $params = {
148             hold_key=>undef,
149             @_,};
150              
151 4 50       16 print __PACKAGE__."::hold_release($params->{hold_key})\n" if $Debug;
152 4         21 $self->_request(_pfreeze( 'hold_release', $params, $Debug));
153             }
154              
155             ######################################################################
156             ######################################################################
157             #### Scheduling
158              
159             sub best {
160 4 50 33 4 1 977 my $self = shift; ($self && ref($self)) or croak 'usage: $self->best';
  4         42  
161 4         38 my %params = (allow_none=>0,
162             @_);
163 4 50       15 print __PACKAGE__."::best()\n" if $Debug;
164             # Backward compatible best function, scheduling on one host without
165             # need to understand new Hold and ResourceReq structures.
166              
167             # Make a hold element with passed params
168 4         48 my $hold = Schedule::Load::Hold->new(hold_key=>"best",);
169 4         9 $hold->set_fields (%{$self},%params);
  4         49  
170             # Make resource requests with passed params
171 4         62 my $req = Schedule::Load::ResourceReq->new();
172 4         7 $req->set_fields (%{$self},%params);
  4         33  
173 4         48 my $rtn = $self->schedule
174             (resources=>[$req],
175             hold=>$hold,
176             allow_none=>1,
177             %params);
178 4 50       22 return undef if !$rtn;
179 4 50 33     38 return undef if !$rtn || !$rtn->scheduled_hosts;
180 4         14 my @hn = $rtn->scheduled_hostnames;
181 4         98 return $hn[0];
182             }
183              
184             sub jobs {
185 4 50 33 4 1 56 my $self = shift; ($self && ref($self)) or croak 'usage: $self->jobs';
  4         29  
186             #** Old depreciated interface
187 4 50       13 print __PACKAGE__."::jobs()\n" if $Debug;
188 4         29 my @names = $self->idle_host_names(@_);
189 4         22 return ($#names+1);
190             }
191              
192             sub schedule {
193 4     4 1 7 my $self = shift;
194 4         34 my %params = (allow_none=>0,
195             hold=>undef, # Schedule::Load::Hold reference, undef not to hold
196             resources=>[],# Schedule::Load::ResourceReq reference
197             @_);
198              
199 4         12 $self->{scheduled_hosts} = [];
200 4         13 $self->{_schrtn} = undef;
201 4 50       30 $params{resources}[0] or croak "%Error: Not passed any resources=>[] to schedule,";
202              
203 1 50   1   8 use Data::Dumper; print "SCHEDULE: ",Dumper(\%params) if $Debug;
  1         3  
  1         88  
  4         12  
204 4         24 $self->_request(_pfreeze ("schedule", \%params, 0&&$Debug));
205              
206 1 50   1   6 use Data::Dumper; print "RETURN: ",Dumper($self->{_schrtn}) if $Debug;
  1         1  
  1         618  
  4         22  
207 4 50       21 (defined $self->{_schrtn}) or die "%Error: Didn't get proper schedule response\n";
208              
209 4 50       19 if (!$self->{_schrtn}{best}) {
210 0         0 return undef;
211             } else {
212             # Remap the hostnames to references (can't pass refs across a socket!)
213 4         10 foreach my $hostname (@{$self->{_schrtn}{best}}) {
  4         227  
214 4         41 my $host = $self->get_host($hostname);
215 4 50       18 if (!$host) {
216             # It's a host that wasn't in our cache....
217 0 0       0 print " Gethost $hostname failed, retrying caching\n" if $Debug;
218 0         0 $self->kill_cache;
219 0         0 $self->fetch;
220 0         0 $host = $self->get_host($hostname);
221 0 0       0 if (!$host) {
222 0 0       0 print " Gethost $hostname retry failed\n" if $Debug;
223 0         0 return undef; # Next scheduler attempt should make sense of it all...
224             }
225             }
226 4         17 push @{$self->{scheduled_hosts}}, $host;
  4         25  
227             }
228             }
229 4         31 return $self;
230             }
231              
232             sub night_hours_p {
233             # Return true if working hours
234 0   0 0 0 0 my $working = ((localtime->hour >= 7 && localtime->hour < 22)
235             && (localtime->wday >= 1 && localtime->wday < 6)); # M-F
236 0         0 return !$working;
237             }
238              
239             ######################################################################
240             ######################################################################
241             #### Changing persistent store's on a host
242              
243             sub set_stored {
244 2 50 33 2 1 6 my $self = shift; ($self && ref($self)) or croak 'usage: $self->hosts)';
  2         26  
245 2         11 my $params = {
246             host=>undef,
247             #set_const=>undef, # If true, put into constant rather than stored data
248             @_,};
249              
250 2 50       7 print __PACKAGE__."::set_stored($params->{host})\n" if $Debug;
251 2         9 $self->_fetch_if_unfetched();
252              
253 2         7 my $host = $self->get_host($params->{host});
254 2 50       9 ($host) or die "%Error: Host $params->{host} not found, so not set\n";
255              
256 2         14 $self->_request(_pfreeze( 'report_fwd_set', $params, $Debug));
257 2         18 $self->fetch();
258             }
259              
260             sub _set_host_stored {
261 0     0     my $self = shift;
262 0           my $host = shift;
263 0           my $var = shift;
264 0           my $value = shift;
265             }
266              
267             ######################################################################
268             #### Package return
269             1;
270              
271             ######################################################################
272             __END__