~percona-toolkit-dev/percona-toolkit/pqd-enhanced-resume-file

503.6.1 by Daniel Nichter
s/Percona Inc/Percona Ireland Ltd/g
1
# This program is copyright 2010-2011 Percona Ireland Ltd.
2 by Daniel Nichter
Add lib/, t/lib/, and sandbox/. All modules are updated and passing on MySQL 5.1.
2
# Feedback and improvements are welcome.
3
#
4
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
5
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
6
# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
7
#
8
# This program is free software; you can redistribute it and/or modify it under
9
# the terms of the GNU General Public License as published by the Free Software
10
# Foundation, version 2; OR the Perl Artistic License.  On UNIX and similar
11
# systems, you can issue `man perlgpl' or `man perlartistic' to read these
12
# licenses.
13
#
14
# You should have received a copy of the GNU General Public License along with
15
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16
# Place, Suite 330, Boston, MA  02111-1307  USA.
17
# ###########################################################################
18 by Daniel Nichter
Remove $Revision$ and finish re-branding modules. Rename MaatkitTest.pm to PerconaTest.pm. Put copyrights on one line.
18
# Advisor package
2 by Daniel Nichter
Add lib/, t/lib/, and sandbox/. All modules are updated and passing on MySQL 5.1.
19
# ###########################################################################
9 by Daniel Nichter
Move module docu to work for NaturalDocs.
20
{
2 by Daniel Nichter
Add lib/, t/lib/, and sandbox/. All modules are updated and passing on MySQL 5.1.
21
# Package: Advisor
22
# Advisor loads, checks, and runs rules for the various mk-*-advisor tools.
23
package Advisor;
24
25
use strict;
26
use warnings FATAL => 'all';
27
use English qw(-no_match_vars);
134 by Daniel Nichter
Replace MKDEBUG with PTDEBUG in modules.
28
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
2 by Daniel Nichter
Add lib/, t/lib/, and sandbox/. All modules are updated and passing on MySQL 5.1.
29
30
# Sub: new
31
#
32
# Parameters:
33
#   %args - Arguments
34
#
35
# Required Arguments:
36
#   match_type   - How rules match: "bool" or "pos"
37
#   ignore_rules - Hashref with rule IDs to ignore
38
#
39
# Returns:
40
#   Advisor object
41
sub new {
42
   my ( $class, %args ) = @_;
43
   foreach my $arg ( qw(match_type) ) {
44
      die "I need a $arg argument" unless $args{$arg};
45
   }
46
47
   my $self = {
48
      %args,
49
      rules          => [],  # Rules from all advisor modules.
50
      rule_index_for => {},  # Maps rules by ID to their array index in $rules.
51
      rule_info      => {},  # ID, severity, description, etc. for each rule.
52
   };
53
54
   return bless $self, $class;
55
}
56
57
# Sub: load_rules
58
#   Load rules from the given advisor module.  Will die on duplicate
59
#   rule IDs.
60
#
61
# Parameters:
62
#   $advisor - An *AdvisorRules module, like <QueryAdvisorRules>
63
sub load_rules {
64
   my ( $self, $advisor ) = @_;
65
   return unless $advisor;
134 by Daniel Nichter
Replace MKDEBUG with PTDEBUG in modules.
66
   PTDEBUG && _d('Loading rules from', ref $advisor);
2 by Daniel Nichter
Add lib/, t/lib/, and sandbox/. All modules are updated and passing on MySQL 5.1.
67
68
   # Starting index value in rules arrayref for these rules.
69
   # This is >0 if rules from other advisor modules have
70
   # already been loaded.
71
   my $i = scalar @{$self->{rules}};
72
73
   RULE:
74
   foreach my $rule ( $advisor->get_rules() ) {
75
      my $id = $rule->{id};
76
      if ( $self->{ignore_rules}->{"$id"} ) {
134 by Daniel Nichter
Replace MKDEBUG with PTDEBUG in modules.
77
         PTDEBUG && _d("Ignoring rule", $id);
2 by Daniel Nichter
Add lib/, t/lib/, and sandbox/. All modules are updated and passing on MySQL 5.1.
78
         next RULE;
79
      }
80
      die "Rule $id already exists and cannot be redefined"
81
         if defined $self->{rule_index_for}->{$id};
82
      push @{$self->{rules}}, $rule;
83
      $self->{rule_index_for}->{$id} = $i++;
84
   }
85
86
   return;
87
}
88
89
# Sub: load_rule_info
90
#   Load rule information (severity and description) from the given advisor
91
#   module.
92
#
93
# Parameters:
94
#   $advisor - An *AdvisorRules module, like <QueryAdvisorRules>
95
sub load_rule_info {
96
   my ( $self, $advisor ) = @_;
97
   return unless $advisor;
134 by Daniel Nichter
Replace MKDEBUG with PTDEBUG in modules.
98
   PTDEBUG && _d('Loading rule info from', ref $advisor);
2 by Daniel Nichter
Add lib/, t/lib/, and sandbox/. All modules are updated and passing on MySQL 5.1.
99
   my $rules = $self->{rules};
100
   foreach my $rule ( @$rules ) {
101
      my $id = $rule->{id};
102
      if ( $self->{ignore_rules}->{"$id"} ) {
103
         # This shouldn't happen.  load_rules() should keep any ignored
104
         # rules out of $self->{rules}.
105
         die "Rule $id was loaded but should be ignored";
106
      }
107
      my $rule_info = $advisor->get_rule_info($id);
108
      next unless $rule_info;
109
      die "Info for rule $id already exists and cannot be redefined"
110
         if $self->{rule_info}->{$id};
111
      $self->{rule_info}->{$id} = $rule_info;
112
   }
113
   return;
114
}
115
116
117
# Sub: run_rules
118
#   Run all rules from all advisors loaded ealier.
119
#
120
# Parameters:
121
#   %args - Arguments passed through to each rule's coderef
122
#
123
# Returns:
124
#   An arrayref of rule IDs that matched and arrayref of pos
125
#   where those rules matched (if <new()> match_type is "bool").
126
sub run_rules {
127
   my ( $self, %args ) = @_;
128
   my @matched_rules;
129
   my @matched_pos;
130
   my $rules      = $self->{rules};
131
   my $match_type = lc $self->{match_type};
132
   foreach my $rule ( @$rules ) {
133
      eval {
134
         my $match = $rule->{code}->(%args);
135
         if ( $match_type eq 'pos' ) {
136
            if ( defined $match ) {
134 by Daniel Nichter
Replace MKDEBUG with PTDEBUG in modules.
137
               PTDEBUG && _d('Matches rule', $rule->{id}, 'near pos', $match);
2 by Daniel Nichter
Add lib/, t/lib/, and sandbox/. All modules are updated and passing on MySQL 5.1.
138
               push @matched_rules, $rule->{id};
139
               push @matched_pos,   $match;
140
            }
141
         }
142
         elsif ( $match_type eq 'bool' ) {
143
            if ( $match ) {
134 by Daniel Nichter
Replace MKDEBUG with PTDEBUG in modules.
144
               PTDEBUG && _d("Matches rule", $rule->{id});
2 by Daniel Nichter
Add lib/, t/lib/, and sandbox/. All modules are updated and passing on MySQL 5.1.
145
               push @matched_rules, $rule->{id};
146
            }
147
         }
148
      };
149
      if ( $EVAL_ERROR ) {
150
         warn "Code for rule $rule->{id} caused an error: $EVAL_ERROR";
151
      }
152
   }
153
   return \@matched_rules, \@matched_pos;
154
};
155
156
157
# Sub: get_rule_info
158
#   Get the information for a rule by ID.
159
#
160
# Parameters:
161
#   $id - Rule ID
162
#
163
# Returns:
164
#   Hashref with the rule's information (id, severity, description)
165
sub get_rule_info {
166
   my ( $self, $id ) = @_;
167
   return unless $id;
168
   return $self->{rule_info}->{$id};
169
}
170
171
sub _d {
172
   my ($package, undef, $line) = caller 0;
173
   @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
174
        map { defined $_ ? $_ : 'undef' }
175
        @_;
176
   print STDERR "# $package:$line $PID ", join(' ', @_), "\n";
177
}
178
179
1;
180
}
181
# ###########################################################################
182
# End Advisor package
183
# ###########################################################################