some error handling for fs.dir(...) == nil
[project/luci.git] / applications / luci-statistics / luasrc / statistics / datatree.lua
1 module("luci.statistics.datatree", package.seeall)
2
3 local util = require("luci.util")
4 local sys  = require("luci.sys")
5 local fs   = require("luci.fs")
6 local uci  = require("luci.model.uci").Session()
7 local sections = uci:sections( "luci_statistics" )
8
9
10 Instance = util.class()
11
12 function Instance.__init__( self, host )
13         self._host    = host or sections.collectd.Hostname or sys.hostname()
14         self._libdir  = sections.collectd.PluginDir        or "/usr/lib/collectd"
15         self._rrddir  = sections.collectd_rrdtool.DataDir  or "/tmp/rrd"
16
17         self._libdir  = self._libdir:gsub("/$","")
18         self._rrddir  = self._rrddir:gsub("/$","")
19         self._plugins = { }
20
21         self:_scan()
22 end
23
24 function Instance._mkpath( self, plugin, pinstance )
25         local dir = self._rrddir .. "/" .. self._host
26
27         if type(plugin) == "string" and plugin:len() > 0 then
28                 dir = dir .. "/" .. plugin
29
30                 if type(pinstance) == "string" and pinstance:len() > 0 then
31                         dir = dir .. "-" .. pinstance
32                 end
33         end
34
35         return dir
36 end
37
38 function Instance._notzero( self, table )
39         for k in pairs(table) do
40                 return true
41         end
42
43         return false
44 end
45
46 function Instance._scan( self )
47         local dir = fs.dir( self._libdir )
48         if not dir then
49                 return
50         end
51         for i, plugin in ipairs( dir ) do
52                 if plugin:match("%w+.so") then
53                         self._plugins[ plugin:gsub(".so", "") ] = { }
54                 end
55         end
56
57         for plugin, instances in pairs( self._plugins ) do
58
59                 local dirs = fs.dir( self:_mkpath() )
60
61                 if type(dirs) == "table" then
62                         for i, dir in ipairs(dirs) do
63                                 if dir:find( plugin .. "%-" ) or dir == plugin then
64                                         local instance = ""
65
66                                         if dir ~= plugin then
67                                                 instance = dir:gsub( plugin .. "%-", "", 1 )
68                                         end
69
70                                         instances[instance] = { }
71                                 end
72                         end
73                 end
74
75                 for instance, data_instances in pairs( instances ) do
76
77                         dirs = fs.dir( self:_mkpath( plugin, instance ) )
78
79                         if type(dirs) == "table" then
80                                 for i, file in ipairs(dirs) do
81                                         if file:find("%.rrd") then
82                                                 file = file:gsub("%.rrd","")
83
84                                                 local data_type
85                                                 local data_instance
86
87                                                 if file:find("%-") then
88                                                         data_type     = file:gsub( "%-.+","" )
89                                                         data_instance = file:gsub( "[^%-]-%-", "", 1 )
90                                                 else
91                                                         data_type     = file
92                                                         data_instance = ""
93                                                 end
94
95                                                 if not data_instances[data_type] then
96                                                         data_instances[data_type] = { data_instance }
97                                                 else
98                                                         table.insert( data_instances[data_type], data_instance )
99                                                 end
100                                         end
101                                 end
102                         end
103                 end
104         end
105 end
106
107
108 function Instance.plugins( self )
109         local rv = { }
110
111         for plugin, val in pairs( self._plugins ) do
112                 if self:_notzero( val ) then
113                         table.insert( rv, plugin )
114                 end
115         end
116
117         return rv
118 end
119
120 function Instance.plugin_instances( self, plugin )
121         local rv = { }
122
123         for instance, val in pairs( self._plugins[plugin] ) do
124                 table.insert( rv, instance )
125         end
126
127         return rv
128 end
129
130 function Instance.data_types( self, plugin, instance )
131         local rv = { }
132         local p  = self._plugins[plugin]
133
134         if type(p) == "table" and type(p[instance]) == "table" then
135                 for type, val in pairs(p[instance]) do
136                         table.insert( rv, type )
137                 end
138         end
139
140         return rv
141 end
142
143 function Instance.data_instances( self, plugin, instance, dtype )
144         local rv = { }
145         local p  = self._plugins[plugin]
146
147         if type(p) == "table" and type(p[instance]) == "table" and type(p[instance][dtype]) == "table" then
148                 for i, instance in ipairs(p[instance][dtype]) do
149                         table.insert( rv, instance )
150                 end
151         end
152
153         return rv
154 end