Revert "curl_xml.c: avoid using uninitalized variable in error message"
[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 stacking));
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   stacking => 'stacking', # GenericStacked only
52   ignore_unknown => 'ignoreunknown' # GenericStacked only
53 );
54
55 return (1);
56
57 sub _create_object
58 {
59   my $module = shift;
60   my $obj;
61
62   # Surpress warnings and error messages caused by the eval.
63   local $SIG{__WARN__} = sub { return (1); print STDERR "WARNING: " . join (', ', @_) . "\n"; };
64   local $SIG{__DIE__}  = sub { return (1); print STDERR "FATAL: "   . join (', ', @_) . "\n"; };
65
66   eval <<PERL;
67   require $module;
68   \$obj = ${module}->new ();
69 PERL
70   if (!$obj)
71   {
72     return;
73   }
74
75   return ($obj);
76 } # _create_object
77
78 sub _load_module_from_config
79 {
80   my $conf = shift;
81
82   my $module = $conf->{'module'};
83   my $obj;
84   
85   if ($module && !($module =~ m/::/))
86   {
87     $module = "Collectd::Graph::Type::$module";
88   }
89
90   if ($module)
91   {
92     $obj = _create_object ($module);
93     if (!$obj)
94     {
95       cluck ("Creating an $module object failed");
96       return;
97     }
98   }
99   else
100   {
101     $obj = Collectd::Graph::Type->new ();
102     if (!$obj)
103     {
104       cluck ("Creating an Collectd::Graph::Type object failed");
105       return;
106     }
107   }
108
109   for (@ScalarMembers) # {{{
110   {
111     my $member = $_;
112     my $key = $MemberToConfigMap{$member};
113     my $val;
114
115     if (!defined $conf->{$key})
116     {
117       next;
118     }
119     $val = $conf->{$key};
120     
121     if (ref ($val) ne '')
122     {
123       cluck ("Invalid value type for $key: " . ref ($val));
124       next;
125     }
126
127     $obj->{$member} = $val;
128   } # }}}
129
130   for (@ArrayMembers) # {{{
131   {
132     my $member = $_;
133     my $key = $MemberToConfigMap{$member};
134     my $val;
135
136     if (!defined $conf->{$key})
137     {
138       next;
139     }
140     $val = $conf->{$key};
141     
142     if (ref ($val) eq 'ARRAY')
143     {
144       $obj->{$member} = $val;
145     }
146     elsif (ref ($val) eq '')
147     {
148       $obj->{$member} = [split (' ', $val)];
149     }
150     else
151     {
152       cluck ("Invalid value type for $key: " . ref ($val));
153     }
154   } # }}}
155
156   for (@DSMappedMembers) # {{{
157   {
158     my $member = $_;
159     my $key = $MemberToConfigMap{$member};
160     my @val_list;
161
162     if (!defined $conf->{$key})
163     {
164       next;
165     }
166
167     if (ref ($conf->{$key}) eq 'ARRAY')
168     {
169       @val_list = @{$conf->{$key}};
170     }
171     elsif (ref ($conf->{$key}) eq '')
172     {
173       @val_list = ($conf->{$key});
174     }
175     else
176     {
177       cluck ("Invalid value type for $key: " . ref ($conf->{$key}));
178       next;
179     }
180
181     for (@val_list)
182     {
183       my $line = $_;
184       my $ds;
185       my $val;
186
187       if (!defined ($line) || (ref ($line) ne ''))
188       {
189         next;
190       }
191
192       ($ds, $val) = split (' ', $line, 2);
193       if (!$ds || !$val)
194       {
195         next;
196       }
197
198       $obj->{$member} ||= {};
199       $obj->{$member}{$ds} = $val;
200     } # for (@val_list)
201   } # }}} for (@DSMappedMembers)
202
203   return ($obj);
204 } # _load_module_from_config
205
206 sub _load_module_generic
207 {
208   my $type = shift;
209   my $module = ucfirst (lc ($type));
210   my $obj;
211
212   $module =~ s/[^A-Za-z_]//g;
213   $module =~ s/_([A-Za-z])/\U$1\E/g;
214
215   $obj = _create_object ($module);
216   if (!$obj)
217   {
218     $obj = Collectd::Graph::Type->new ();
219     if (!$obj)
220     {
221       cluck ("Creating an Collectd::Graph::Type object failed");
222       return;
223     }
224   }
225
226   return ($obj);
227 } # _load_module_generic
228
229 =head1 EXPORTED FUNCTIONS
230
231 =over 4
232
233 =item B<tl_load_type> (I<$type>)
234
235 Does whatever is necessary to get an object with which to graph RRD files of
236 type I<$type>.
237
238 =cut
239
240 sub tl_load_type
241 {
242   my $type = shift;
243   my $conf = gc_get_config ();
244
245   if (defined ($conf) && defined ($conf->{'type'}{$type}))
246   {
247     return (_load_module_from_config ($conf->{'type'}{$type}));
248   }
249   else
250   {
251     return (_load_module_generic ($type));
252   }
253 } # tl_load_type
254
255 =back
256
257 =head1 SEE ALSO
258
259 L<Collectd::Graph::Type::GenericStacked>
260
261 =head1 AUTHOR AND LICENSE
262
263 Copyright (c) 2008 by Florian Forster
264 E<lt>octoE<nbsp>atE<nbsp>verplant.orgE<gt>. Licensed under the terms of the GNU
265 General Public License, VersionE<nbsp>2 (GPLv2).
266
267 =cut
268
269 # vim: set shiftwidth=2 softtabstop=2 tabstop=8 et fdm=marker :