/usr/share/awesome/lib/flaw/provider.lua is in awesome-extra 2012061101.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | -- flaw, a Lua OO management framework for Awesome WM widgets.
-- Copyright (C) 2009,2010,2011 David Soulayrol <david.soulayrol AT gmail DOT net>
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- Grab environment.
local pairs = pairs
local os = os
local setmetatable = setmetatable
local capi = {
timer = timer,
}
local flaw = {
helper = require('flaw.helper'),
}
--- Providers core mechanisms.
--
-- <p>In <b>flaw</b>, all data is gathered by provider objects which,
-- in an attempt to minimize resources usage, can be shared among
-- gadgets. The providers can poll disks or memory at a given rate for
-- their information, or can be updated by scripts or direct
-- <b>Lua</b> invocation, like <b>awful</b> callbacks. When updated,
-- providers notify the gadgets that have subscribed to them.</p>
--
-- <p>Providers are normally handled automatically when a gadget is
-- created. You only have to take care of them when you are writing
-- your own gadget, or if you want to create a new provider, or extend
-- an existing one. <b>flaw</b> already implements many providers for
-- common system information. The existing providers are usually
-- defined in the module of the widget type they serve.</p>
--
-- <p>A provider is identified by its type and an identifier, which
-- must remain unique for one type. The provider type usually
-- represents the module of this provider and can be composed of any
-- character. Thus, it is common to create a new provider prototype
-- this way:</p>
--
-- <div class='example'>
-- flaw.provider.Provider:new{ type = _NAME }
-- </div>
--
-- <p>All created providers are kept in a <a
-- href='#_providers_cache'>global store</a> from which they can be
-- retrieved anytime. Note that this store has normally no use for the
-- user, but allows gadgets to share providers.</p>
--
-- @author David Soulayrol <david.soulayrol AT gmail DOT com>
-- @copyright 2009,2010,2011 David Soulayrol
module('flaw.provider')
--- Global providers store.
--
-- <p>This table stores all the registered provider
-- instances. Providers are sorted by their type first, and then by
-- their ID. The store is private to the <code>provider</code>
-- module. It can be accessed using its <a
-- href='#get'><code>get</code></a>, and <a
-- href='#add'><code>add</code></a> functions.</p>
--
-- @class table
-- @name _providers_cache
local _providers_cache = {}
--- Store a provider instance.
--
-- <p>This function stores the given provider in the global providers
-- store. It fails if the instance is invalid, that is if it is nil or
-- if its type is nil.</p>
--
-- <p>You normally do not have to call this function since it is
-- silently invoked each time a gadget instantiates its provider.</p>
--
-- @param p the provider prototype to store.
function add(p)
if p == nil or p.id == nil then
flaw.helper.debug.error('flaw.provider.provider_add: invalid provider.')
else
if _providers_cache[p.type] == nil then
_providers_cache[p.type] = {}
end
_providers_cache[p.type][p.id] = p
end
end
--- Retrieve a provider instance.
--
-- <p>This function returns the provider matching the given
-- information. It immediately fails if the given type or identifier
-- is nil. It also fails if no instance in the store matches the given
-- parameters.</p>
--
-- @param type the type of the provider to retrieve.
-- @param id the uniquer identifier of the provider to retrieve.
-- @return The matching provider instance, or nil if information was
-- incomplete or if there is no such provider.
function get(type, id)
if type == nil or id == nil then
flaw.helper.debug.error('flaw.provider.provider_get: invalid information.')
else
return _providers_cache[type] ~= nil
and _providers_cache[type][id] or nil
end
end
--- The Provider prototype.
--
-- <p>This is the root prototype of all providers. It defines nothing
-- but the prototype's type and a method for gadgets subscription.</p>
--
-- @class table
-- @name Provider
Provider = { type = 'unknown' }
--- Provider constructor.
--
-- <p>Remember that providers are normally handled automatically when
-- a gadget is created. This constructor is only used internally, or
-- to create new gadget prototypes.</p>
--
-- @param o a table with default values.
-- @return The brand new provider.
function Provider:new(o)
o = o or {}
o.data = o.data or {}
o.subscribers = o.subscribers or {}
setmetatable(o, self)
self.__index = self
return o
end
--- Subscribe a gadget to this provider.
--
-- <p>This is the method a gadget automatically uses, when created by
-- the gadget factory, to register itself to its provider. The root
-- provider does strictly nothing with this subscription, but any
-- active provider uses the subscribers list to update its
-- gadgets.</p>
--
-- <p>This method immediately fails if the given gadget is nil. On
-- success, the gadget is stored in the provider internal subscribers
-- list.</p>
--
-- @param g the gadget subscriber.
-- @return True if the subscriber was correctly stored, False otherwise.
function Provider:subscribe(g)
if g == nil then
flaw.helper.debug.error('flaw.provider.Provider:subscribe: invalid gadget')
return false
end
self.subscribers[g] = { timestamp = os.time() }
return true
end
--- Refresh gadgets subscribed to this provider.
--
-- <p>This method is a facility for providers to invoke all the
-- gadgets refresh when they are done with data gathering.</p>
function Provider:refresh_gadgets()
for g, props in pairs(self.subscribers) do
props['timestamp'] = self.timestamp
g:update()
end
end
--- The Cyclic Provider prototype.
--
-- <p>This specialized provider is the root of all the providers
-- needing to provide cyclic information, based on files, network and
-- so on, rather than on events. Cyclic providers poll resources
-- status from system only when necessary (ie. when the gadget with
-- the shortest refresh rate demands it).</p>
--
-- <p>The CyclicProvider relies on a C API timer. The timer timeout
-- value defaults to 60 seconds but is updated each time a gadget
-- starts to use the provider, if its own rate is shorter. Note that
-- the higher rate demand only will be served in time, all others will
-- be refreshed using a comparison between their timestamp and the
-- refresh date. For example, if a provider is asked to refresh every
-- 10 seconds and then every 3 seconds, its timer will be set to 3
-- seconds. The second gadget will be refreshed exactly in time,
-- whereas the first will be refreshed at 12 seconds, 21 seconds, 30
-- seconds, and so on.</p>
--
-- <p>All CyclicProvider also define a <code>timestamp</code> value
-- which can be used in specific treatments to know the last refresh
-- date.</p>
--
-- @class table
-- @name CyclicProvider
CyclicProvider = Provider:new{ type = 'unknown.cyclic', timestamp = 0, timer = nil }
--- Subscribe a gadget to this provider.
--
-- <p>The CyclicProvider specialised method adds the poll timer
-- handling to the parent method. It also requires the gadget's rate
-- as second argument (which defaults to 60s).</p>
--
-- <p>This method immediately fails if the given gadget is nil. On
-- success, the gadget is stored in the provider internal subscribers
-- list.</p>
--
-- @param g the gadget subscriber.
-- @param rate the new poll interval asked by the gadget.
-- @return True if the subscriber was correctly stored and the timer
-- correctly started or reconfigured (if necessary), False otherwise.
function CyclicProvider:subscribe(g, rate)
rate = rate or 60
if Provider.subscribe(self, g) then
self.subscribers[g].rate = rate
local start = false
if self.timer == nil then
self.timer = capi.timer{ timeout = 60 }
self.timer:add_signal('timeout', function() self:refresh() end, true)
start = true
end
if rate < self.timer.timeout then
self.timer.timeout = rate
end
if start then
self.timer:start()
end
-- Initial refresh.
self:refresh(g)
return true
end
return false
end
--- Refresh the provider status.
--
-- <p>This callback is invoked by the provider timer, which timeouts
-- at the highest asked rate. The actual refresh process is dedicated
-- to the <code>do_refresh</code> method, which is called with no
-- argument. This definition depends on the provider role, and should
-- be defined in all derived prototypes.</p>
--
-- <p>After refresh is done, the gadgets are redrawn.</p>
--
-- @param g if provided, this gadget only is refreshed.
-- @return True is the provider did refresh its data set since the
-- given gadget last asked for the refresh.
function CyclicProvider:refresh(g)
if self.do_refresh then
self:do_refresh()
if g ~= nil then
self.subscribers[g].timestamp = self.timestamp
g:update()
else
self:refresh_gadgets()
end
else
flaw.helper.debug.warn(
'CyclicProvider ' .. self.type .. '.' .. self.id .. ' misses do_refresh()')
end
end
--- Refresh gadgets subscribed to this provider.
--
-- <p>Redefined here to handle the rate required by the different
-- gadgets. All child providers should rely on the
-- <code>refresh</code> method which calls directly this one.</p>
function CyclicProvider:refresh_gadgets(force)
local force = force or false
self.timestamp = os.time()
for g, props in pairs(self.subscribers) do
if force or props['timestamp'] + props['rate'] <= self.timestamp then
props['timestamp'] = self.timestamp
g:update()
end
end
end
|