FailureTest.pm 6.93 KB
Newer Older
1 2 3 4
=pod 

=head1 NAME

5
    Bio::EnsEMBL::Hive::RunnableDB::FailureTest
6 7 8

=head1 SYNOPSIS

9 10 11
    This is a RunnableDB module that implements Bio::EnsEMBL::Hive::Process interface
    and is ran by Workers during the execution of eHive pipelines.
    It is not generally supposed to be instantiated and used outside of this framework.
12

13
    Please refer to Bio::EnsEMBL::Hive::Process documentation to understand the basics of the RunnableDB interface.
14

15
    Please refer to Bio::EnsEMBL::Hive::PipeConfig::* pipeline configuration files to understand how to configure pipelines.
16 17 18

=head1 DESCRIPTION

19 20 21 22 23 24 25 26 27 28 29 30 31
    This RunnableDB module is used to test failure of jobs in the hive system.

    It is intended for development/training purposes only.

    Available parameters:

        param('value'):         is essentially your job's number.
                                If you are intending to create 100 jobs, let the param('value') take consecutive values from 1 to 100.

        param('divisor'):       defines the failure rate for this particular analysis. If the modulo (value % divisor) is 0, the job will fail.
                                For example, if param('divisor')==5, jobs with 5, 10, 15, 20, 25,... param('value') will fail.

        param('state'):         defines the state in which the jobs of this analysis may be failing.
32

33
        param('lethal_after'):  makes jobs' failures lethal when 'value' is greater than this parameter
34

35
        param('time_FETCH_INPUT'):  time in seconds that the job will spend sleeping in FETCH_INPUT state.
36

37
        param('time_RUN'):          time in seconds that the job will spend sleeping in RUN state.
38

39
        param('time_WRITE_OUTPUT'): time in seconds that the job will spend sleeping in WRITE_OUTPUT state.
40

41
=head1 LICENSE
42

43
    Copyright [1999-2015] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
Matthieu Muffato's avatar
Matthieu Muffato committed
44
    Copyright [2016-2018] EMBL-European Bioinformatics Institute
45

46 47
    Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
    You may obtain a copy of the License at
48

49
         http://www.apache.org/licenses/LICENSE-2.0
50

51 52 53
    Unless required by applicable law or agreed to in writing, software distributed under the License
    is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and limitations under the License.
54

55 56
=head1 CONTACT

57
    Please subscribe to the Hive mailing list:  http://listserver.ebi.ac.uk/mailman/listinfo/ehive-users  to discuss Hive-related questions or to be notified of our updates
58 59

=cut
60 61


62
package Bio::EnsEMBL::Hive::RunnableDB::FailureTest;
63 64 65

use strict;

66
use base ('Bio::EnsEMBL::Hive::Process');
67

68 69 70 71
BEGIN {
#    die "Could not compile this nonsense!";
}

72
=head2 param_defaults
73

74
    Description : Implements param_defaults() interface method of Bio::EnsEMBL::Hive::Process that defines module defaults for parameters.
75 76 77

=cut

78
sub param_defaults {
79

80
    return {
81 82
        'value'         => 1,       # normally you generate a batch of jobs with different values of param('value')
        'divisor'       => 2,       # but the same param('divisor') and see how every param('divisor')'s job will crash
83
        'state'         => 'RUN',   # the state in which the process may commit apoptosis ('FETCH_INPUT', 'RUN' or 'WRITE_OUTPUT')
84
        'lethal_after'  => 0,       # If value is above this (nonzero) threshold, job's death becomes lethal to the worker.
85

86
        'time_FETCH_INPUT'  => 0,   # how much time fetch_input()  will spend in sleeping state
87 88
        'time_RUN'          => 1,   # how much time run()          will spend in sleeping state
        'time_WRITE_OUTPUT' => 0,   # how much time write_output() will spend in sleeping state
89 90

        'grab_mln'          => 0,   # how many millions of numeric elements to allocate
91 92 93
    };
}

94 95 96 97 98 99 100 101 102 103 104 105 106

=head2 pre_cleanup

    Title   :  pre_cleanup
    Function:  sublcass can implement functions related to cleaning up the database/filesystem after the previous unsuccessful run.
                Here we just define it to see when the job gets into this state.
               
=cut

sub pre_cleanup {
}


107 108 109 110 111 112 113 114 115
=head2 fetch_input

    Description : Implements fetch_input() interface method of Bio::EnsEMBL::Hive::Process that is used to read in parameters and load data.
                  Here it only calls dangerous_math() subroutine.

=cut

sub fetch_input {
    my $self = shift @_;
116

117
    $self->dangerous_math('FETCH_INPUT');
118 119
}

120

121 122
=head2 run

123
    Description : Implements run() interface method of Bio::EnsEMBL::Hive::Process that is used to perform the main bulk of the job (minus input and output).
124
                  Here it only calls dangerous_math() subroutine.
125 126 127

=cut

128 129
sub run {
    my $self = shift @_;
130

131 132 133 134 135
    my $mem_ref;
    if(my $grab_mln = $self->param('grab_mln')) {
        $mem_ref = $self->grab_memory( $grab_mln );
    }

136
    $self->dangerous_math('RUN');
137 138
}

139

140 141
=head2 write_output

142
    Description : Implements write_output() interface method of Bio::EnsEMBL::Hive::Process that is used to deal with job's output after the execution.
143
                  Here it only calls dangerous_math() subroutine.
144 145 146 147

=cut

sub write_output {
148
    my $self = shift @_;
149

150 151 152
    $self->dangerous_math('WRITE_OUTPUT');
}

153 154 155 156 157 158 159 160 161 162 163 164 165 166

=head2 post_cleanup

    Title   :  post_cleanup
    Function:  sublcass can implement functions related to cleaning up after running one job
               (destroying non-trivial data structures in memory).
                Here we just define it to see when the job gets into this state.
               
=cut

sub post_cleanup {
}


167 168 169 170 171 172 173 174 175 176 177
=head2 dangerous_math

    Description: an internal subroutine that will first sleep for some predefined time,
                 and then either return or crash if $value is an integral multiple of $divisor.

=cut

sub dangerous_math {
    my ($self, $current_state) = @_;

        # First, sleep as required:
178 179
    my $seconds_to_sleep = $self->param('time_'.$current_state);
    sleep( $seconds_to_sleep );
180 181 182 183 184 185 186 187

    my $state   = $self->param('state');
    return if($current_state ne $state);

    my $value   = $self->param('value')   or die "param('value') has to be a nonzero integer";
    my $divisor = $self->param('divisor') or die "param('divisor') has to be a nonzero integer";

    if($value % $divisor == 0) {
188 189 190 191 192

        if(my $lethal_after = $self->param('lethal_after')) {
            if($value>$lethal_after) { # take the Worker with us into the grave
                $self->input_job->lethal_for_worker(1);
            }
193 194 195 196
        }

        die "Preprogrammed death since $value is a multiple of $divisor";
    }
197 198
}

199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214

sub grab_memory {
    my ($self, $grab_mln) = @_;

    my $elements        = $grab_mln*1_000_000;
    my $estimated_megs  = $grab_mln*69 + 23;    # empirically found by running on farm3, may differ elsewhere

    $|=1;

    $self->warning("Allocating $elements elements, which should map to approximately $estimated_megs megabytes");

    my @mem = (1..$elements);

    return \@mem;
}

215
1;
216