contrib/collection3: Add the "IgnoreUnknown" config option.
[collectd.git] / contrib / collection3 / lib / Collectd / Graph / TypeLoader.pm
1 package Collectd::Graph::TypeLoader;
2
3 =head1 NAME
4
5 Collectd::Graph::TypeLoader - Load a module according to the "type"
6
7 =cut
8
9 # Copyright (C) 2008,2009  Florian octo Forster <octo at verplant.org>
10 #
11 # This program is free software; you can redistribute it and/or modify it under
12 # the terms of the GNU General Public License as published by the Free Software
13 # Foundation; only version 2 of the License is applicable.
14 #
15 # This program is distributed in the hope that it will be useful, but WITHOUT
16 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18 # details.
19 #
20 # You should have received a copy of the GNU General Public License along with
21 # this program; if not, write to the Free Software Foundation, Inc.,
22 # 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23
24 use strict;
25 use warnings;
26
27 use Carp (qw(cluck confess));
28 use Exporter ();
29 use Config::General ('ParseConfig');
30 use Collectd::Graph::Config ('gc_get_config');
31 use Collectd::Graph::Type ();
32
33 @Collectd::Graph::TypeLoader::ISA = ('Exporter');
34 @Collectd::Graph::TypeLoader::EXPORT_OK = ('tl_load_type');
35
36 our @ArrayMembers = (qw(data_sources rrd_opts custom_order));
37 our @ScalarMembers = (qw(rrd_title rrd_format rrd_vertical scale ignore_unknown));
38 our @DSMappedMembers = (qw(ds_names rrd_colors));
39
40 our %MemberToConfigMap =
41 (
42   data_sources => 'datasources',
43   ds_names => 'dsname',
44   rrd_title => 'rrdtitle',
45   rrd_opts => 'rrdoptions',
46   rrd_format => 'rrdformat',
47   rrd_vertical => 'rrdverticallabel',
48   rrd_colors => 'color',
49   scale => 'scale', # GenericIO only
50   custom_order => 'order', # GenericStacked only
51   ignore_unknown => 'ignoreunknown' # GenericStacked only
52 );
53
54 return (1);
55
56 sub _create_object
57 {
58   my $module = shift;
59   my $obj;
60
61   local $SIG{__WARN__} = sub {};
62   local $SIG{__DIE__} = sub {};
63
64   eval <<PERL;
65   require $module;
66   \$obj = ${module}->new ();
67 PERL
68   if (!$obj)
69   {
70     return;
71   }
72
73   return ($obj);
74 } # _create_object
75
76 sub _load_module_from_config
77 {
78   my $conf = shift;
79
80   my $module = $conf->{'module'};
81   my $obj;
82   
83   if ($module && !($module =~ m/::/))
84   {
85     $module = "Collectd::Graph::Type::$module";
86   }
87
88   if ($module)
89   {
90     $obj = _create_object ($module);
91     if (!$obj)
92     {
93       cluck ("Creating an $module object failed");
94       return;
95     }
96   }
97   else
98   {
99     $obj = Collectd::Graph::Type->new ();
100     if (!$obj)
101     {
102       cluck ("Creating an Collectd::Graph::Type object failed");
103       return;
104     }
105   }
106
107   for (@ScalarMembers) # {{{
108   {
109     my $member = $_;
110     my $key = $MemberToConfigMap{$member};
111     my $val;
112
113     if (!defined $conf->{$key})
114     {
115       next;
116     }
117     $val = $conf->{$key};
118     
119     if (ref ($val) ne '')
120     {
121       cluck ("Invalid value type for $key: " . ref ($val));
122       next;
123     }
124
125     $obj->{$member} = $val;
126   } # }}}
127
128   for (@ArrayMembers) # {{{
129   {
130     my $member = $_;
131     my $key = $MemberToConfigMap{$member};
132     my $val;
133
134     if (!defined $conf->{$key})
135     {
136       next;
137     }
138     $val = $conf->{$key};
139     
140     if (ref ($val) eq 'ARRAY')
141     {
142       $obj->{$member} = $val;
143     }
144     elsif (ref ($val) eq '')
145     {
146       $obj->{$member} = [split (' ', $val)];
147     }
148     else
149     {
150       cluck ("Invalid value type for $key: " . ref ($val));
151     }
152   } # }}}
153
154   for (@DSMappedMembers) # {{{
155   {
156     my $member = $_;
157     my $key = $MemberToConfigMap{$member};
158     my @val_list;
159
160     if (!defined $conf->{$key})
161     {
162       next;
163     }
164
165     if (ref ($conf->{$key}) eq 'ARRAY')
166     {
167       @val_list = @{$conf->{$key}};
168     }
169     elsif (ref ($conf->{$key}) eq '')
170     {
171       @val_list = ($conf->{$key});
172     }
173     else
174     {
175       cluck ("Invalid value type for $key: " . ref ($conf->{$key}));
176       next;
177     }
178
179     for (@val_list)
180     {
181       my $line = $_;
182       my $ds;
183       my $val;
184
185       if (!defined ($line) || (ref ($line) ne ''))
186       {
187         next;
188       }
189
190       ($ds, $val) = split (' ', $line, 2);
191       if (!$ds || !$val)
192       {
193         next;
194       }
195
196       $obj->{$member} ||= {};
197       $obj->{$member}{$ds} = $val;
198     } # for (@val_list)
199   } # }}} for (@DSMappedMembers)
200
201   return ($obj);
202 } # _load_module_from_config
203
204 sub _load_module_generic
205 {
206   my $type = shift;
207   my $module = ucfirst (lc ($type));
208   my $obj;
209
210   $module =~ s/[^A-Za-z_]//g;
211   $module =~ s/_([A-Za-z])/\U$1\E/g;
212
213   $obj = _create_object ($module);
214   if (!$obj)
215   {
216     $obj = Collectd::Graph::Type->new ();
217     if (!$obj)
218     {
219       cluck ("Creating an Collectd::Graph::Type object failed");
220       return;
221     }
222   }
223
224   return ($obj);
225 } # _load_module_generic
226
227 =head1 EXPORTED FUNCTIONS
228
229 =over 4
230
231 =item B<tl_load_type> (I<$type>)
232
233 Does whatever is necessary to get an object with which to graph RRD files of
234 type I<$type>.
235
236 =cut
237
238 sub tl_load_type
239 {
240   my $type = shift;
241   my $conf = gc_get_config ();
242
243   if (defined ($conf) && defined ($conf->{'type'}{$type}))
244   {
245     return (_load_module_from_config ($conf->{'type'}{$type}));
246   }
247   else
248   {
249     return (_load_module_generic ($type));
250   }
251 } # tl_load_type
252
253 =back
254
255 =head1 SEE ALSO
256
257 L<Collectd::Graph::Type::GenericStacked>
258
259 =head1 AUTHOR AND LICENSE
260
261 Copyright (c) 2008 by Florian Forster
262 E<lt>octoE<nbsp>atE<nbsp>verplant.orgE<gt>. Licensed under the terms of the GNU
263 General Public License, VersionE<nbsp>2 (GPLv2).
264
265 =cut
266
267 # vim: set shiftwidth=2 softtabstop=2 tabstop=8 et fdm=marker :