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::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));
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 );
53 return (1);
55 sub _create_object
56 {
57 my $module = shift;
58 my $obj;
60 local $SIG{__WARN__} = sub {};
61 local $SIG{__DIE__} = sub {};
63 eval <<PERL;
64 require $module;
65 \$obj = ${module}->new ();
66 PERL
67 if (!$obj)
68 {
69 return;
70 }
72 return ($obj);
73 } # _create_object
75 sub _load_module_from_config
76 {
77 my $conf = shift;
79 my $module = $conf->{'module'};
80 my $obj;
82 if ($module && !($module =~ m/::/))
83 {
84 $module = "Collectd::Graph::Type::$module";
85 }
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 }
106 for (@ScalarMembers) # {{{
107 {
108 my $member = $_;
109 my $key = $MemberToConfigMap{$member};
110 my $val;
112 if (!defined $conf->{$key})
113 {
114 next;
115 }
116 $val = $conf->{$key};
118 if (ref ($val) ne '')
119 {
120 cluck ("Invalid value type for $key: " . ref ($val));
121 next;
122 }
124 $obj->{$member} = $val;
125 } # }}}
127 for (@ArrayMembers) # {{{
128 {
129 my $member = $_;
130 my $key = $MemberToConfigMap{$member};
131 my $val;
133 if (!defined $conf->{$key})
134 {
135 next;
136 }
137 $val = $conf->{$key};
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 } # }}}
153 for (@DSMappedMembers) # {{{
154 {
155 my $member = $_;
156 my $key = $MemberToConfigMap{$member};
157 my @val_list;
159 if (!defined $conf->{$key})
160 {
161 next;
162 }
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 }
178 for (@val_list)
179 {
180 my $line = $_;
181 my $ds;
182 my $val;
184 if (!defined ($line) || (ref ($line) ne ''))
185 {
186 next;
187 }
189 ($ds, $val) = split (' ', $line, 2);
190 if (!$ds || !$val)
191 {
192 next;
193 }
195 $obj->{$member} ||= {};
196 $obj->{$member}{$ds} = $val;
197 } # for (@val_list)
198 } # }}} for (@DSMappedMembers)
200 return ($obj);
201 } # _load_module_from_config
203 sub _load_module_generic
204 {
205 my $type = shift;
206 my $module = ucfirst (lc ($type));
207 my $obj;
209 $module =~ s/[^A-Za-z_]//g;
210 $module =~ s/_([A-Za-z])/\U$1\E/g;
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 }
223 return ($obj);
224 } # _load_module_generic
226 =head1 EXPORTED FUNCTIONS
228 =over 4
230 =item B<tl_load_type> (I<$type>)
232 Does whatever is necessary to get an object with which to graph RRD files of
233 type I<$type>.
235 =cut
237 sub tl_load_type
238 {
239 my $type = shift;
240 my $conf = gc_get_config ();
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
252 =back
254 =head1 SEE ALSO
256 L<Collectd::Graph::Type::GenericStacked>
258 =head1 AUTHOR AND LICENSE
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).
264 =cut
266 # vim: set shiftwidth=2 softtabstop=2 tabstop=8 et fdm=marker :