1 package Collectd::Graph::TypeLoader;
3 =head1 NAME
5 Collectd::Graph::TypeLoader - Load a module according to the "type"
7 =cut
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.
24 use strict;
25 use warnings;
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 ();
33 @Collectd::Graph::TypeLoader::ISA = ('Exporter');
34 @Collectd::Graph::TypeLoader::EXPORT_OK = ('tl_load_type');
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));
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 );
54 return (1);
56 sub _create_object
57 {
58 my $module = shift;
59 my $obj;
61 local $SIG{__WARN__} = sub { print STDERR "WARNING: " . join (', ', @_) . "\n"; };
62 local $SIG{__DIE__} = sub { print STDERR "FATAL: " . join (', ', @_) . "\n"; };
64 eval <<PERL;
65 require $module;
66 \$obj = ${module}->new ();
67 PERL
68 if (!$obj)
69 {
70 return;
71 }
73 return ($obj);
74 } # _create_object
76 sub _load_module_from_config
77 {
78 my $conf = shift;
80 my $module = $conf->{'module'};
81 my $obj;
83 if ($module && !($module =~ m/::/))
84 {
85 $module = "Collectd::Graph::Type::$module";
86 }
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 }
107 for (@ScalarMembers) # {{{
108 {
109 my $member = $_;
110 my $key = $MemberToConfigMap{$member};
111 my $val;
113 if (!defined $conf->{$key})
114 {
115 next;
116 }
117 $val = $conf->{$key};
119 if (ref ($val) ne '')
120 {
121 cluck ("Invalid value type for $key: " . ref ($val));
122 next;
123 }
125 $obj->{$member} = $val;
126 } # }}}
128 for (@ArrayMembers) # {{{
129 {
130 my $member = $_;
131 my $key = $MemberToConfigMap{$member};
132 my $val;
134 if (!defined $conf->{$key})
135 {
136 next;
137 }
138 $val = $conf->{$key};
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 } # }}}
154 for (@DSMappedMembers) # {{{
155 {
156 my $member = $_;
157 my $key = $MemberToConfigMap{$member};
158 my @val_list;
160 if (!defined $conf->{$key})
161 {
162 next;
163 }
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 }
179 for (@val_list)
180 {
181 my $line = $_;
182 my $ds;
183 my $val;
185 if (!defined ($line) || (ref ($line) ne ''))
186 {
187 next;
188 }
190 ($ds, $val) = split (' ', $line, 2);
191 if (!$ds || !$val)
192 {
193 next;
194 }
196 $obj->{$member} ||= {};
197 $obj->{$member}{$ds} = $val;
198 } # for (@val_list)
199 } # }}} for (@DSMappedMembers)
201 return ($obj);
202 } # _load_module_from_config
204 sub _load_module_generic
205 {
206 my $type = shift;
207 my $module = ucfirst (lc ($type));
208 my $obj;
210 $module =~ s/[^A-Za-z_]//g;
211 $module =~ s/_([A-Za-z])/\U$1\E/g;
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 }
224 return ($obj);
225 } # _load_module_generic
227 =head1 EXPORTED FUNCTIONS
229 =over 4
231 =item B<tl_load_type> (I<$type>)
233 Does whatever is necessary to get an object with which to graph RRD files of
234 type I<$type>.
236 =cut
238 sub tl_load_type
239 {
240 my $type = shift;
241 my $conf = gc_get_config ();
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
253 =back
255 =head1 SEE ALSO
257 L<Collectd::Graph::Type::GenericStacked>
259 =head1 AUTHOR AND LICENSE
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).
265 =cut
267 # vim: set shiftwidth=2 softtabstop=2 tabstop=8 et fdm=marker :