blob: 813b0b2750b061619d8af88530f100aa3247e529 [file] [log] [blame]
Zack Williams41513bf2018-07-07 20:08:35 -07001/*
2 * Copyright 2017-present Open Networking Foundation
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 */
Stephane Barbarie35595062018-02-08 08:34:39 -050016package common
17
18import (
19 "github.com/sirupsen/logrus"
20 "sync"
21 "time"
22)
23
24/*
25 IntervalHandler is used to run a routine at regular intervals and provide all the necessary
26 utilities to manage the execution.
27*/
28
29type IntervalHandler struct {
30 // Interval period in between each execution (in seconds?)
31 Interval int
32 // function to execute after each interval
33 function func()
34 // Channel listening to execution events
35 execute chan _ExecutionState
36 // Channel listening for a termination event
37 terminate chan struct{}
38 // Current execution state of the handler
39 state _ExecutionState
40 wg sync.WaitGroup
41}
42
43// Define execution state constants
44type _ExecutionState uint8
45
46const (
47 STARTED _ExecutionState = iota
48 STOPPED
49 PAUSED
50 RESUMED
51)
52
53// Execute state string equivalents
54var _ExecutionStateEnum = []string{
55 "STARTED",
56 "STOPPED",
57 "PAUSED",
58 "RESUMED",
59}
60
61func (s _ExecutionState) String() string {
62 return _ExecutionStateEnum[s]
63}
64
65/*
66NewIntervalHandler instantiates a new interval based function execution handler
67*/
68func NewIntervalHandler(interval int, function func()) *IntervalHandler {
69 handler := &IntervalHandler{
70 Interval: interval,
71 function: function,
72 }
73
74 handler.execute = make(chan _ExecutionState)
75 handler.terminate = make(chan struct{})
76 handler.state = STOPPED
77
78 return handler
79}
80
81/*
82_Execute is a routine running concurrently and listening to execution events
83*/
84func (h *IntervalHandler) _Execute() {
85 defer h.wg.Done()
86 for {
87 select {
88 case h.state = <-h.execute:
89 Logger().WithFields(logrus.Fields{
90 "handler": h,
91 }).Debug("Processing execution state")
92 switch h.state {
93 case STARTED:
94 case PAUSED:
95 case RESUMED:
96 h.state = STARTED
97 case STOPPED:
98 fallthrough
99 default:
100 h.terminate <- struct{}{}
101 }
102
103 case <-h.terminate:
104 return
105
106 default:
107 if h.state == STARTED {
108 h.function()
109 time.Sleep(time.Duration(h.Interval) * time.Second)
110 } else {
111 // TODO: replace hardcoded delay with a configurable parameter
112 time.Sleep(1 * time.Second)
113 }
114 }
115 }
116}
117
118/*
119Start initiates the interval based function execution
120*/
121func (h *IntervalHandler) Start() {
122 Logger().WithFields(logrus.Fields{
123 "handler": h,
124 }).Info("Starting interval handler")
125
126 if h.execute == nil {
127 return
128 }
129 if h.state == STOPPED {
130 go h._Execute()
131 h.execute <- STARTED
132 }
133}
134
135/*
136Pause interrupts the interval based function execution
137*/
138func (h *IntervalHandler) Pause() {
139 Logger().WithFields(logrus.Fields{
140 "handler": h,
141 }).Info("Pausing interval handler")
142
143 if h.execute == nil || h.state == STOPPED {
144 return
145 }
146 if h.state == STARTED {
147 h.execute <- PAUSED
148 }
149}
150
151/*
152Resume continues the interval based function execution
153*/
154func (h *IntervalHandler) Resume() {
155 Logger().WithFields(logrus.Fields{
156 "handler": h,
157 }).Info("Resuming interval handler")
158
159 if h.execute == nil || h.state == STOPPED {
160 return
161 }
162 if h.state == PAUSED {
163 h.execute <- RESUMED
164 }
165}
166
167/*
168Stop terminates the interval based function execution
169*/
170func (h *IntervalHandler) Stop() {
171 Logger().WithFields(logrus.Fields{
172 "handler": h,
173 }).Info("Stopping interval handler")
174
175 if h.execute == nil || h.state == STOPPED {
176 return
177 }
178 h.execute <- STOPPED
179}