fortrangoingonforty/fgof-devloop / 414cce8

Browse files

Build devloop model

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
414cce80a570e3986ebe27bcf8bf282fd6d409fc
Parents
c29fbe8
Tree
a7d80f1

2 changed files

StatusFile+-
M src/fgof_devloop.f90 225 1
M src/fgof_devloop_types.f90 47 0
src/fgof_devloop.f90modified
@@ -1,27 +1,251 @@
1
 module fgof_devloop
1
 module fgof_devloop
2
-  use fgof_devloop_types, only : devloop_state
2
+  use fgof_devloop_types, only : &
3
+    FGOF_DEVLOOP_DECISION_IDLE, &
4
+    FGOF_DEVLOOP_DECISION_RESTART, &
5
+    FGOF_DEVLOOP_DECISION_RUN, &
6
+    FGOF_DEVLOOP_DECISION_STOP, &
7
+    FGOF_DEVLOOP_TRIGGER_CHANGE, &
8
+    FGOF_DEVLOOP_TRIGGER_MANUAL, &
9
+    FGOF_DEVLOOP_TRIGGER_NONE, &
10
+    FGOF_DEVLOOP_TRIGGER_START, &
11
+    devloop_cycle, &
12
+    devloop_decision, &
13
+    devloop_options, &
14
+    devloop_state, &
15
+    devloop_trigger
3
   implicit none
16
   implicit none
4
   private
17
   private
5
 
18
 
6
   character(len=*), parameter :: FGOF_DEVLOOP_BACKEND_MODEL = "model"
19
   character(len=*), parameter :: FGOF_DEVLOOP_BACKEND_MODEL = "model"
7
 
20
 
21
+  public :: begin_devloop_cycle
22
+  public :: clear_devloop_cycle
23
+  public :: clear_devloop_decision
24
+  public :: clear_devloop_options
8
   public :: clear_devloop_state
25
   public :: clear_devloop_state
26
+  public :: clear_devloop_trigger
9
   public :: devloop_backend_name
27
   public :: devloop_backend_name
28
+  public :: devloop_change_trigger
29
+  public :: devloop_cycle
30
+  public :: devloop_decision
31
+  public :: devloop_manual_trigger
32
+  public :: devloop_options
33
+  public :: devloop_start_trigger
10
   public :: devloop_state
34
   public :: devloop_state
35
+  public :: devloop_trigger
36
+  public :: finish_devloop_cycle
37
+  public :: FGOF_DEVLOOP_DECISION_IDLE
38
+  public :: FGOF_DEVLOOP_DECISION_RESTART
39
+  public :: FGOF_DEVLOOP_DECISION_RUN
40
+  public :: FGOF_DEVLOOP_DECISION_STOP
41
+  public :: FGOF_DEVLOOP_TRIGGER_CHANGE
42
+  public :: FGOF_DEVLOOP_TRIGGER_MANUAL
43
+  public :: FGOF_DEVLOOP_TRIGGER_NONE
44
+  public :: FGOF_DEVLOOP_TRIGGER_START
45
+  public :: should_start_on_open
46
+  public :: start_devloop
47
+  public :: stop_devloop
11
 
48
 
12
 contains
49
 contains
13
 
50
 
51
+  function clear_devloop_options() result(options)
52
+    type(devloop_options) :: options
53
+
54
+    options%run_on_start = .true.
55
+    options%restart_on_change = .true.
56
+    options%stop_on_failure = .false.
57
+    options%max_failures = 0
58
+  end function clear_devloop_options
59
+
60
+  function clear_devloop_trigger() result(trigger)
61
+    type(devloop_trigger) :: trigger
62
+
63
+    trigger%kind = FGOF_DEVLOOP_TRIGGER_NONE
64
+    trigger%change_count = 0
65
+    trigger%reason = ""
66
+  end function clear_devloop_trigger
67
+
68
+  function clear_devloop_cycle() result(cycle)
69
+    type(devloop_cycle) :: cycle
70
+
71
+    cycle%id = 0
72
+    cycle%trigger_kind = FGOF_DEVLOOP_TRIGGER_NONE
73
+    cycle%change_count = 0
74
+    cycle%exit_code = 0
75
+    cycle%started = .false.
76
+    cycle%finished = .false.
77
+    cycle%succeeded = .false.
78
+    cycle%reason = ""
79
+  end function clear_devloop_cycle
80
+
81
+  function clear_devloop_decision() result(decision)
82
+    type(devloop_decision) :: decision
83
+
84
+    decision%kind = FGOF_DEVLOOP_DECISION_IDLE
85
+    decision%cycle_id = 0
86
+    decision%failure_count = 0
87
+    decision%should_run = .false.
88
+    decision%should_stop = .false.
89
+    decision%reason = ""
90
+  end function clear_devloop_decision
91
+
14
   function clear_devloop_state() result(state)
92
   function clear_devloop_state() result(state)
15
     type(devloop_state) :: state
93
     type(devloop_state) :: state
16
 
94
 
95
+    state%options = clear_devloop_options()
96
+    state%last_cycle = clear_devloop_cycle()
17
     state%cycle_count = 0
97
     state%cycle_count = 0
98
+    state%consecutive_failures = 0
18
     state%active = .false.
99
     state%active = .false.
100
+    state%running = .false.
101
+    state%stopped = .false.
19
   end function clear_devloop_state
102
   end function clear_devloop_state
20
 
103
 
104
+  subroutine start_devloop(state, options)
105
+    type(devloop_state), intent(inout) :: state
106
+    type(devloop_options), intent(in), optional :: options
107
+
108
+    state = clear_devloop_state()
109
+    if (present(options)) then
110
+      state%options = options
111
+    end if
112
+    call normalize_options(state%options)
113
+    state%active = .true.
114
+  end subroutine start_devloop
115
+
116
+  subroutine stop_devloop(state)
117
+    type(devloop_state), intent(inout) :: state
118
+
119
+    state%active = .false.
120
+    state%running = .false.
121
+    state%stopped = .true.
122
+  end subroutine stop_devloop
123
+
124
+  function should_start_on_open(state) result(should_start)
125
+    type(devloop_state), intent(in) :: state
126
+    logical :: should_start
127
+
128
+    should_start = state%active .and. state%options%run_on_start .and. &
129
+                   .not. state%running .and. .not. state%stopped
130
+  end function should_start_on_open
131
+
132
+  function devloop_start_trigger() result(trigger)
133
+    type(devloop_trigger) :: trigger
134
+
135
+    trigger = clear_devloop_trigger()
136
+    trigger%kind = FGOF_DEVLOOP_TRIGGER_START
137
+    trigger%reason = "start"
138
+  end function devloop_start_trigger
139
+
140
+  function devloop_change_trigger(change_count, reason) result(trigger)
141
+    integer, intent(in) :: change_count
142
+    character(len=*), intent(in), optional :: reason
143
+    type(devloop_trigger) :: trigger
144
+
145
+    trigger = clear_devloop_trigger()
146
+    trigger%kind = FGOF_DEVLOOP_TRIGGER_CHANGE
147
+    trigger%change_count = max(0, change_count)
148
+    if (present(reason)) then
149
+      trigger%reason = reason
150
+    else
151
+      trigger%reason = "change"
152
+    end if
153
+  end function devloop_change_trigger
154
+
155
+  function devloop_manual_trigger(reason) result(trigger)
156
+    character(len=*), intent(in), optional :: reason
157
+    type(devloop_trigger) :: trigger
158
+
159
+    trigger = clear_devloop_trigger()
160
+    trigger%kind = FGOF_DEVLOOP_TRIGGER_MANUAL
161
+    if (present(reason)) then
162
+      trigger%reason = reason
163
+    else
164
+      trigger%reason = "manual"
165
+    end if
166
+  end function devloop_manual_trigger
167
+
168
+  function begin_devloop_cycle(state, trigger) result(cycle)
169
+    type(devloop_state), intent(inout) :: state
170
+    type(devloop_trigger), intent(in) :: trigger
171
+    type(devloop_cycle) :: cycle
172
+
173
+    cycle = clear_devloop_cycle()
174
+    if (.not. state%active) return
175
+    if (state%running) return
176
+    if (state%stopped) return
177
+    if (trigger%kind == FGOF_DEVLOOP_TRIGGER_NONE) return
178
+    if (trigger%kind == FGOF_DEVLOOP_TRIGGER_CHANGE .and. .not. state%options%restart_on_change) return
179
+
180
+    state%cycle_count = state%cycle_count + 1
181
+    state%running = .true.
182
+
183
+    cycle%id = state%cycle_count
184
+    cycle%trigger_kind = trigger%kind
185
+    cycle%change_count = trigger%change_count
186
+    cycle%started = .true.
187
+    cycle%reason = trigger%reason
188
+    state%last_cycle = cycle
189
+  end function begin_devloop_cycle
190
+
191
+  function finish_devloop_cycle(state, succeeded, exit_code) result(decision)
192
+    type(devloop_state), intent(inout) :: state
193
+    logical, intent(in) :: succeeded
194
+    integer, intent(in), optional :: exit_code
195
+    type(devloop_decision) :: decision
196
+    integer :: actual_exit_code
197
+
198
+    decision = clear_devloop_decision()
199
+    if (.not. state%running) return
200
+
201
+    actual_exit_code = 0
202
+    if (present(exit_code)) actual_exit_code = exit_code
203
+
204
+    state%running = .false.
205
+    state%last_cycle%finished = .true.
206
+    state%last_cycle%succeeded = succeeded
207
+    state%last_cycle%exit_code = actual_exit_code
208
+
209
+    decision%cycle_id = state%last_cycle%id
210
+
211
+    if (succeeded) then
212
+      state%consecutive_failures = 0
213
+      decision%kind = FGOF_DEVLOOP_DECISION_IDLE
214
+      decision%reason = "cycle succeeded"
215
+      return
216
+    end if
217
+
218
+    state%consecutive_failures = state%consecutive_failures + 1
219
+    decision%failure_count = state%consecutive_failures
220
+    if (state%options%stop_on_failure .or. failure_limit_reached(state)) then
221
+      decision%kind = FGOF_DEVLOOP_DECISION_STOP
222
+      decision%should_stop = .true.
223
+      decision%reason = "failure policy stopped the loop"
224
+      call stop_devloop(state)
225
+    else
226
+      decision%kind = FGOF_DEVLOOP_DECISION_RESTART
227
+      decision%should_run = .true.
228
+      decision%reason = "cycle failed; restart allowed"
229
+    end if
230
+  end function finish_devloop_cycle
231
+
21
   function devloop_backend_name() result(name)
232
   function devloop_backend_name() result(name)
22
     character(len=:), allocatable :: name
233
     character(len=:), allocatable :: name
23
 
234
 
24
     name = FGOF_DEVLOOP_BACKEND_MODEL
235
     name = FGOF_DEVLOOP_BACKEND_MODEL
25
   end function devloop_backend_name
236
   end function devloop_backend_name
26
 
237
 
238
+  subroutine normalize_options(options)
239
+    type(devloop_options), intent(inout) :: options
240
+
241
+    if (options%max_failures < 0) options%max_failures = 0
242
+  end subroutine normalize_options
243
+
244
+  logical function failure_limit_reached(state) result(reached)
245
+    type(devloop_state), intent(in) :: state
246
+
247
+    reached = state%options%max_failures > 0 .and. &
248
+              state%consecutive_failures >= state%options%max_failures
249
+  end function failure_limit_reached
250
+
27
 end module fgof_devloop
251
 end module fgof_devloop
src/fgof_devloop_types.f90modified
@@ -2,9 +2,56 @@ module fgof_devloop_types
2
   implicit none
2
   implicit none
3
   private
3
   private
4
 
4
 
5
+  integer, parameter, public :: FGOF_DEVLOOP_TRIGGER_NONE = 0
6
+  integer, parameter, public :: FGOF_DEVLOOP_TRIGGER_START = 1
7
+  integer, parameter, public :: FGOF_DEVLOOP_TRIGGER_CHANGE = 2
8
+  integer, parameter, public :: FGOF_DEVLOOP_TRIGGER_MANUAL = 3
9
+  integer, parameter, public :: FGOF_DEVLOOP_DECISION_IDLE = 0
10
+  integer, parameter, public :: FGOF_DEVLOOP_DECISION_RUN = 1
11
+  integer, parameter, public :: FGOF_DEVLOOP_DECISION_RESTART = 2
12
+  integer, parameter, public :: FGOF_DEVLOOP_DECISION_STOP = 3
13
+
14
+  type, public :: devloop_options
15
+    logical :: run_on_start = .true.
16
+    logical :: restart_on_change = .true.
17
+    logical :: stop_on_failure = .false.
18
+    integer :: max_failures = 0
19
+  end type devloop_options
20
+
21
+  type, public :: devloop_trigger
22
+    integer :: kind = FGOF_DEVLOOP_TRIGGER_NONE
23
+    integer :: change_count = 0
24
+    character(len=:), allocatable :: reason
25
+  end type devloop_trigger
26
+
27
+  type, public :: devloop_cycle
28
+    integer :: id = 0
29
+    integer :: trigger_kind = FGOF_DEVLOOP_TRIGGER_NONE
30
+    integer :: change_count = 0
31
+    integer :: exit_code = 0
32
+    logical :: started = .false.
33
+    logical :: finished = .false.
34
+    logical :: succeeded = .false.
35
+    character(len=:), allocatable :: reason
36
+  end type devloop_cycle
37
+
38
+  type, public :: devloop_decision
39
+    integer :: kind = FGOF_DEVLOOP_DECISION_IDLE
40
+    integer :: cycle_id = 0
41
+    integer :: failure_count = 0
42
+    logical :: should_run = .false.
43
+    logical :: should_stop = .false.
44
+    character(len=:), allocatable :: reason
45
+  end type devloop_decision
46
+
5
   type, public :: devloop_state
47
   type, public :: devloop_state
48
+    type(devloop_options) :: options
49
+    type(devloop_cycle) :: last_cycle
6
     integer :: cycle_count = 0
50
     integer :: cycle_count = 0
51
+    integer :: consecutive_failures = 0
7
     logical :: active = .false.
52
     logical :: active = .false.
53
+    logical :: running = .false.
54
+    logical :: stopped = .false.
8
   end type devloop_state
55
   end type devloop_state
9
 
56
 
10
 end module fgof_devloop_types
57
 end module fgof_devloop_types