6223eaa0cf663407cd1139d4dfefb1137524455a
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 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::Type ();
32 @Collectd::Graph::TypeLoader::ISA = ('Exporter');
33 @Collectd::Graph::TypeLoader::EXPORT_OK = ('tl_read_config', 'tl_load_type');
35 our $Configuration = undef;
37 our @ArrayMembers = (qw(data_sources rrd_opts custom_order));
38 our @ScalarMembers = (qw(rrd_title rrd_format rrd_vertical scale));
39 our @DSMappedMembers = (qw(ds_names rrd_colors));
41 our %MemberToConfigMap =
42 (
43 data_sources => 'datasources',
44 ds_names => 'dsname',
45 rrd_title => 'rrdtitle',
46 rrd_opts => 'rrdoptions',
47 rrd_format => 'rrdformat',
48 rrd_vertical => 'rrdverticallabel',
49 rrd_colors => 'color',
50 scale => 'scale', # GenericIO only
51 custom_order => 'order' # GenericStacked only
52 );
54 return (1);
56 =head1 EXPORTED FUNCTIONS
58 =over 4
60 =item B<tl_read_config> (I<$file>)
62 Reads the configuration from the file located at I<$file>.
64 =cut
66 sub tl_read_config
67 {
68 my $file = shift;
69 my %conf;
71 if ($Configuration)
72 {
73 return (1);
74 }
76 %conf = ParseConfig (-ConfigFile => $file,
77 -LowerCaseNames => 1,
78 -UseApacheInclude => 1,
79 -IncludeDirectories => 1,
80 ($Config::General::VERSION >= 2.38) ? (-IncludeAgain => 0) : (),
81 -MergeDuplicateBlocks => 1,
82 -CComments => 0);
83 if (!%conf)
84 {
85 return;
86 }
88 $Configuration = \%conf;
89 return (1);
90 } # tl_read_config
92 sub _create_object
93 {
94 my $module = shift;
95 my $obj;
97 local $SIG{__WARN__} = sub {};
98 local $SIG{__DIE__} = sub {};
100 eval <<PERL;
101 require $module;
102 \$obj = ${module}->new ();
103 PERL
104 if (!$obj)
105 {
106 return;
107 }
109 return ($obj);
110 } # _create_object
112 sub _load_module_from_config
113 {
114 my $conf = shift;
116 my $module = $conf->{'module'};
117 my $obj;
119 if ($module && !($module =~ m/::/))
120 {
121 $module = "Collectd::Graph::Type::$module";
122 }
124 if ($module)
125 {
126 print STDERR "\$module = $module;\n";
127 $obj = _create_object ($module);
128 if (!$obj)
129 {
130 cluck ("Creating an $module object failed");
131 return;
132 }
133 }
134 else
135 {
136 $obj = Collectd::Graph::Type->new ();
137 if (!$obj)
138 {
139 cluck ("Creating an Collectd::Graph::Type object failed");
140 return;
141 }
142 }
144 for (@ScalarMembers) # {{{
145 {
146 my $member = $_;
147 my $key = $MemberToConfigMap{$member};
148 my $val;
150 if (!defined $conf->{$key})
151 {
152 next;
153 }
154 $val = $conf->{$key};
156 if (ref ($val) ne '')
157 {
158 cluck ("Invalid value type for $key: " . ref ($val));
159 next;
160 }
162 $obj->{$member} = $val;
163 } # }}}
165 for (@ArrayMembers) # {{{
166 {
167 my $member = $_;
168 my $key = $MemberToConfigMap{$member};
169 my $val;
171 if (!defined $conf->{$key})
172 {
173 next;
174 }
175 $val = $conf->{$key};
177 if (ref ($val) eq 'ARRAY')
178 {
179 $obj->{$member} = $val;
180 }
181 elsif (ref ($val) eq '')
182 {
183 $obj->{$member} = [split (' ', $val)];
184 }
185 else
186 {
187 cluck ("Invalid value type for $key: " . ref ($val));
188 }
189 } # }}}
191 for (@DSMappedMembers) # {{{
192 {
193 my $member = $_;
194 my $key = $MemberToConfigMap{$member};
195 my @val_list;
197 if (!defined $conf->{$key})
198 {
199 next;
200 }
202 if (ref ($conf->{$key}) eq 'ARRAY')
203 {
204 @val_list = @{$conf->{$key}};
205 }
206 elsif (ref ($conf->{$key}) eq '')
207 {
208 @val_list = ($conf->{$key});
209 }
210 else
211 {
212 cluck ("Invalid value type for $key: " . ref ($conf->{$key}));
213 next;
214 }
216 for (@val_list)
217 {
218 my $line = $_;
219 my $ds;
220 my $val;
222 if (!defined ($line) || (ref ($line) ne ''))
223 {
224 next;
225 }
227 ($ds, $val) = split (' ', $line, 2);
228 if (!$ds || !$val)
229 {
230 next;
231 }
233 $obj->{$member} ||= {};
234 $obj->{$member}{$ds} = $val;
236 print STDERR "\$obj->{$member}{$ds} = $val;\n";
237 } # for (@val_list)
238 } # }}} for (@DSMappedMembers)
240 return ($obj);
241 } # _load_module_from_config
243 sub _load_module_generic
244 {
245 my $type = shift;
246 my $module = ucfirst (lc ($type));
247 my $obj;
249 $module =~ s/[^A-Za-z_]//g;
250 $module =~ s/_([A-Za-z])/\U$1\E/g;
252 $obj = _create_object ($module);
253 if (!$obj)
254 {
255 $obj = Collectd::Graph::Type->new ();
256 if (!$obj)
257 {
258 cluck ("Creating an Collectd::Graph::Type object failed");
259 return;
260 }
261 }
263 return ($obj);
264 } # _load_module_generic
266 =item B<tl_load_type> (I<$type>)
268 Does whatever is necessary to get an object with which to graph RRD files of
269 type I<$type>.
271 =cut
273 sub tl_load_type
274 {
275 my $type = shift;
277 if (defined $Configuration->{'type'}{$type})
278 {
279 return (_load_module_from_config ($Configuration->{'type'}{$type}));
280 }
281 else
282 {
283 return (_load_module_generic ($type));
284 }
285 } # tl_load_type
287 =back
289 =head1 SEE ALSO
291 L<Collectd::Graph::Type::GenericStacked>
293 =head1 AUTHOR AND LICENSE
295 Copyright (c) 2008 by Florian Forster
296 E<lt>octoE<nbsp>atE<nbsp>verplant.orgE<gt>. Licensed under the terms of the GNU
297 General Public License, VersionE<nbsp>2 (GPLv2).
299 =cut
301 # vim: set shiftwidth=2 softtabstop=2 tabstop=8 et fdm=marker :