e15002cd415456f4e46ee92e06aec1694e4f0924
[ealt-edge.git] / mep / mepserver / mp1 / arch / workspace / workspace_base.go
1 /*
2  * Copyright 2020 Huawei Technologies Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package workspace
18
19 import (
20         "sync"
21 )
22
23 type PlanIf interface {
24         SetErrorStep(stepName string)
25         UsingSpace(spaceName string)
26         RunBackground(task ...interface{})
27         RunParallel(task ...interface{})
28         RunSerial(task ...interface{})
29 }
30
31 type SpaceIf interface {
32         PlanIf
33         getPlan() *PlanBase
34 }
35
36 type ErrCode int
37
38 const (
39         TaskContinue ErrCode = -1
40         TaskOK       ErrCode = iota
41         TaskFail
42 )
43
44 const FINALLY string = "finally"
45
46
47 type SubGrp struct {
48         Policy     GoPolicy
49         CurStepIdx int
50         StepNames  []string
51         StepObjs   []interface{}
52 }
53
54 func (s *SubGrp) Install(task []interface{}) bool {
55         for _, stepObj := range task {
56                 if stepObj == nil {
57                         return false
58                 }
59                 s.StepObjs = append(s.StepObjs, stepObj)
60         }
61         return true
62 }
63
64 type SerErrInfo struct {
65         ErrCode int
66         Message string
67         GrpIdx  int
68         TaskIdx int
69 }
70
71 type PlanBase struct {
72         SerError  *SerErrInfo
73         PlanName  string
74         SpaceName string
75         ErrStep   string
76         PlanGrp   []SubGrp
77         CurGrpIdx int
78         WtPlan    sync.WaitGroup
79 }
80
81 func (b *PlanBase) SetErrorStep(stepName string) {
82         b.ErrStep = stepName
83 }
84
85 func (b *PlanBase) UsingSpace(spaceName string) {
86         b.SpaceName = spaceName
87 }
88
89 func (b *PlanBase) RunBackground(task ...interface{}) {
90         b.LoadTask(GoBackground, task)
91 }
92
93 func (b *PlanBase) RunParallel(task ...interface{}) {
94         b.LoadTask(GoParallel, task)
95 }
96
97 func (b *PlanBase) RunSerial(task ...interface{}) {
98         b.LoadTask(GoSerial, task)
99 }
100
101 func (b *PlanBase) RunSerialName(task interface{}, name string) {
102         var subGrp SubGrp
103         subGrp.Policy = GoSerial
104         subGrp.Install([]interface{}{task})
105         b.LoadData([]interface{}{task})
106         subGrp.StepNames = []string{name}
107         b.PlanGrp = append(b.PlanGrp, subGrp)
108 }
109
110 func (b *PlanBase) Try(task ...interface{}) {
111         b.SetErrorStep(FINALLY)
112         b.LoadTask(GoSerial, task)
113 }
114
115 func (b *PlanBase) Finally(task interface{}) {
116         var subGrp SubGrp
117         subGrp.Policy = GoSerial
118         subGrp.Install([]interface{}{task})
119         b.LoadData([]interface{}{task})
120         subGrp.StepNames = []string{FINALLY}
121         b.PlanGrp = append(b.PlanGrp, subGrp)
122 }
123
124 func (b *PlanBase) LoadTask(policy GoPolicy, task []interface{}) {
125         var subGrp SubGrp
126         subGrp.Policy = policy
127         subGrp.Install(task)
128         b.LoadData(task)
129         b.PlanGrp = append(b.PlanGrp, subGrp)
130 }
131
132 func (b *PlanBase) LoadData(task []interface{}) bool {
133         for _, stepObj := range task {
134                 if stepObj == nil {
135                         return false
136                 }
137                 stepIf, ok := stepObj.(TaskBaseIf)
138                 if !ok {
139                         continue
140                 }
141                 stepIf.SetSerErrInfo(b.SerError)
142         }
143         return true
144 }
145
146 type SpaceBase struct {
147         PlanBase
148 }
149
150 func (s *SpaceBase) Init() {
151         s.SerError = &SerErrInfo{}
152 }
153
154 func (s *SpaceBase) getPlan() *PlanBase {
155         return &s.PlanBase
156 }
157
158 func GotoErrorStep(curPlan *PlanBase, grpNum int) bool {
159         for idx, stepName := range curPlan.PlanGrp[grpNum].StepNames {
160                 if stepName == curPlan.ErrStep {
161                         if curPlan.CurGrpIdx > grpNum {
162                                 return true
163                         }
164                         curPlan.CurGrpIdx = grpNum
165                         if curPlan.PlanGrp[grpNum].CurStepIdx < idx {
166                                 curPlan.PlanGrp[grpNum].CurStepIdx = idx
167                         }
168                         return true
169                 }
170         }
171         return false
172 }
173
174 func RecordErrInfo(curPlan *PlanBase, stepIdx int) {
175         if curPlan.CurGrpIdx >= len(curPlan.PlanGrp) {
176                 return
177         }
178         curGrp := curPlan.PlanGrp[curPlan.CurGrpIdx]
179         if stepIdx < 0 || stepIdx >= len(curGrp.StepObjs) {
180                 return
181         }
182
183         curPlan.SerError.GrpIdx = curPlan.CurGrpIdx
184         curPlan.SerError.TaskIdx = stepIdx
185         curStep := curGrp.StepObjs[stepIdx]
186         stepIf, ok := curStep.(TaskBaseIf)
187         if !ok {
188                 return
189         }
190         errCode, msg := stepIf.GetErrCode()
191         curPlan.SerError.ErrCode = int(errCode)
192         curPlan.SerError.Message = msg
193 }
194
195 func GotoErrorProc(curPlan *PlanBase) {
196         curPlan.CurGrpIdx++
197         for grpNum := 0; grpNum < len(curPlan.PlanGrp); grpNum++ {
198                 done := GotoErrorStep(curPlan, grpNum)
199                 if done {
200                         break
201                 }
202         }
203 }