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