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