bef5651c6ae6df708bcc52344441965d404afaf9
[project/luci.git] / libs / lpk / luasrc / lpk / core.lua
1 module("luci.lpk.core", package.seeall)
2 require("luci.util")
3
4 Task = luci.util.class()
5
6 function Task.__init__(self, machine, register, start)
7         self.machine = machine
8
9         -- The queue that has to be processed
10         self.work = {start}
11         
12         -- The queue that has to be processed in case of rollback
13         self.done = {}
14         
15         -- The Task register
16         self.register = register
17 end
18
19 function Task.rollback(self)
20         if #self.done < 1 then
21                 return false
22         end
23         
24         local state = table.remove(self.done)
25         local ret, err = pcall(state.rollback, state, self.register)
26         
27         if ret then
28                 return true
29         else
30                 return false, err
31         end
32 end
33
34 function Task.step(self)
35         local state = table.remove(self.work)
36         local ret, next = pcall(state.process, state, self.register)
37         
38         if ret then
39                 if next then
40                         local nstate = self.machine:state(next)
41                         if nstate then
42                                 table.insert(self.work, state)
43                                 table.insert(self.work, nstate)
44                         else
45                                 self.register.error = "Unknown state: " .. next
46                                 return false
47                         end
48                 else
49                         table.insert(self.done, state)
50                 end
51                 
52                 return #self.work > 0 
53         else
54                 self.register.error = next
55                 return false
56         end
57 end
58
59 function Task.perform(self)
60         while self:step() do
61         end
62         
63         if not self.register.error then
64                 return true
65         else
66                 local stat, err
67                 repeat
68                         stat, err = self:rollback()
69                 until not stat
70                 
71                 if err then
72                         self.register.errstr = err
73                         self.register.error = 2
74                 end
75                 
76                 return false
77         end     
78 end
79
80
81 Machine = luci.util.class()
82
83 function Machine.__init__(self, namespace)
84         self.namespace = namespace or _NAME
85 end
86
87 function Machine.state(self, name)
88         local ret, state = pcall(require, self.namespace .. "." .. name)
89         return ret and state
90 end
91
92 function Machine.task(self, name, ...)
93         local start = self:state(name)
94         
95         if type(start) ~= "table" or not start.entry then
96                 return false, "No such command: " .. name
97         end
98         
99         local register = {}
100         
101         return start:entry(register) and Task(self, register, start)
102 end