libs/lpk: Implemented register/stack/state machine

This commit is contained in:
Steven Barth 2008-07-27 17:38:05 +00:00
parent e8c0707534
commit 3b29503f13
9 changed files with 141 additions and 60 deletions

View file

@ -1,38 +1,4 @@
module("luci.lpk", package.seeall)
function getopt( arg, options )
local tab = {}
local args = {}
for k, v in ipairs(arg) do
if v:sub(1, 2) == "--" then
local x = v:find( "=", 1, true )
if x then
tab[ v:sub( 3, x-1 ) ] = v:sub( x+1 )
else
tab[ v:sub( 3 ) ] = true
end
elseif v:sub( 1, 1 ) == "-" then
local y = 2
local l = #v
local jopt
while ( y <= l ) do
jopt = v:sub( y, y )
if options:find( jopt, 1, true ) then
if y < l then
tab[ jopt ] = v:sub( y+1 )
y = l
else
tab[ jopt ] = arg[ k + 1 ]
end
else
tab[ jopt ] = true
end
y = y + 1
end
else
table.insert(args, v)
end
end
return tab, args
end

View file

@ -0,0 +1,103 @@
module("luci.lpk.core", package.seeall)
require("luci.util")
Task = luci.util.class()
function Task.__init__(self, machine, register, start)
self.machine = machine
-- The queue that has to be processed
self.work = {start}
-- The queue that has to be processed in case of rollback
self.done = {}
-- The Task register
self.register = register
end
function Task.rollback(self)
if #self.done < 1 then
return false
end
local state = table.remove(self.done)
local ret, err = pcall(state.rollback, state, self.register)
if ret then
return true
else
return false, err
end
end
function Task.step(self)
local state = table.remove(self.work)
local ret, next = pcall(state.process, state, self.register)
if ret then
if next then
local nstate = self.machine:state(next)
if nstate then
table.insert(self.work, state)
table.insert(self.work, nstate)
else
self.register.error = "Unknown state: " .. next
return false
end
else
table.insert(self.done, state)
end
return #self.work > 0
else
self.register.error = next
return false
end
end
function Task.perform(self)
while self:step() do
end
if not self.register.error then
return true
else
local stat, err
repeat
stat, err = self:rollback()
until not stat
assert(not err, "Machine broken!")
return false, self.register.error
end
end
Machine = luci.util.class()
function Machine.__init__(self, namespace)
self.namespace = namespace or _NAME
end
function Machine.state(self, name)
local ret, state = pcall(require, self.namespace .. "." .. name)
return ret and state
end
function Machine.task(self, name, ...)
local start = self:state(name)
if not start or not start.entry then
error("No such command: " .. name)
end
local register = {}
if start:entry(register) then
return Task(self, register, start)
else
return nil, register.error
end
end

View file

View file

View file

@ -1,25 +0,0 @@
module("luci.lpk.state", package.seeall)
require("luci.util")
State = luci.util.class()
function State.__init__()
self.poststates = {}
self.prestates = {}
end
function State.add_poststate(state)
table.insert(self.poststates, state)
end
function State.add_prestate(state)
table.insert(self.prestates, state)
end
function State.process()
end
function State.handle()
end

View file

@ -0,0 +1,37 @@
module("luci.lpk.util", package.seeall)
function getopt( arg, options )
local tab = {}
local args = {}
for k, v in ipairs(arg) do
if v:sub(1, 2) == "--" then
local x = v:find( "=", 1, true )
if x then
tab[ v:sub( 3, x-1 ) ] = v:sub( x+1 )
else
tab[ v:sub( 3 ) ] = true
end
elseif v:sub( 1, 1 ) == "-" then
local y = 2
local l = #v
local jopt
while ( y <= l ) do
jopt = v:sub( y, y )
if options:find( jopt, 1, true ) then
if y < l then
tab[ jopt ] = v:sub( y+1 )
y = l
else
tab[ jopt ] = arg[ k + 1 ]
end
else
tab[ jopt ] = true
end
y = y + 1
end
else
table.insert(args, v)
end
end
return tab, args
end