packer-plugin-xenserver/builder/xenserver/interruptible_wait.go
Cheng Sun 651274e508 interruptible_wait: evaluate Predicate immediately
Previous behaviour was to wait PredicateInterval before the first
time that the Predicate is evaluated
2014-12-09 16:32:37 +00:00

70 lines
1.3 KiB
Go

package xenserver
import (
"github.com/mitchellh/multistep"
"time"
)
type InterruptibleWait struct {
Predicate func() (result bool, err error)
PredicateInterval time.Duration
Timeout time.Duration
}
type TimeoutError struct{}
func (err TimeoutError) Error() string {
return "Timed out"
}
type InterruptedError struct{}
func (err InterruptedError) Error() string {
return "Interrupted"
}
type PredicateResult struct {
complete bool
err error
}
func (wait InterruptibleWait) Wait(state multistep.StateBag) error {
predicateResult := make(chan PredicateResult, 1)
stopWaiting := make(chan struct{})
defer close(stopWaiting)
go func() {
for {
if complete, err := wait.Predicate(); err != nil || complete {
predicateResult <- PredicateResult{complete, err}
return
}
select {
case <-time.After(wait.PredicateInterval):
// do nothing; loop again
case <-stopWaiting:
return
}
}
}()
timeout := time.After(wait.Timeout)
for {
// wait for either install to complete/error,
// an interrupt to come through, or a timeout to occur
select {
case result := <-predicateResult:
return result.err
case <-time.After(1 * time.Second):
if _, ok := state.GetOk(multistep.StateCancelled); ok {
return InterruptedError{}
}
case <-timeout:
return TimeoutError{}
}
}
}