WIP [VOL-2811] - Incorporate preliminary onu-adapter-go code into opencord repo
- reason "discovery-mibsync-complete" reached (via full MibUpload only, received data won't be stored yet)
- first review comments of patchset #4 considered
(please have a look into our inline-comments in Gerrit to know more about the current state)
- no refactoring done yet
Change-Id: Iac47817f8ce4bd28dd8132f530b0570d57ae99b8
Signed-off-by: Holger Hildebrandt <holger.hildebrandt@adtran.com>
diff --git a/vendor/github.com/eapache/go-resiliency/LICENSE b/vendor/github.com/eapache/go-resiliency/LICENSE
new file mode 100644
index 0000000..698a3f5
--- /dev/null
+++ b/vendor/github.com/eapache/go-resiliency/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Evan Huus
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/vendor/github.com/eapache/go-resiliency/breaker/README.md b/vendor/github.com/eapache/go-resiliency/breaker/README.md
new file mode 100644
index 0000000..2d1b3d9
--- /dev/null
+++ b/vendor/github.com/eapache/go-resiliency/breaker/README.md
@@ -0,0 +1,34 @@
+circuit-breaker
+===============
+
+[![Build Status](https://travis-ci.org/eapache/go-resiliency.svg?branch=master)](https://travis-ci.org/eapache/go-resiliency)
+[![GoDoc](https://godoc.org/github.com/eapache/go-resiliency/breaker?status.svg)](https://godoc.org/github.com/eapache/go-resiliency/breaker)
+[![Code of Conduct](https://img.shields.io/badge/code%20of%20conduct-active-blue.svg)](https://eapache.github.io/conduct.html)
+
+The circuit-breaker resiliency pattern for golang.
+
+Creating a breaker takes three parameters:
+- error threshold (for opening the breaker)
+- success threshold (for closing the breaker)
+- timeout (how long to keep the breaker open)
+
+```go
+b := breaker.New(3, 1, 5*time.Second)
+
+for {
+ result := b.Run(func() error {
+ // communicate with some external service and
+ // return an error if the communication failed
+ return nil
+ })
+
+ switch result {
+ case nil:
+ // success!
+ case breaker.ErrBreakerOpen:
+ // our function wasn't run because the breaker was open
+ default:
+ // some other error
+ }
+}
+```
diff --git a/vendor/github.com/eapache/go-resiliency/breaker/breaker.go b/vendor/github.com/eapache/go-resiliency/breaker/breaker.go
new file mode 100644
index 0000000..f88ca72
--- /dev/null
+++ b/vendor/github.com/eapache/go-resiliency/breaker/breaker.go
@@ -0,0 +1,161 @@
+// Package breaker implements the circuit-breaker resiliency pattern for Go.
+package breaker
+
+import (
+ "errors"
+ "sync"
+ "sync/atomic"
+ "time"
+)
+
+// ErrBreakerOpen is the error returned from Run() when the function is not executed
+// because the breaker is currently open.
+var ErrBreakerOpen = errors.New("circuit breaker is open")
+
+const (
+ closed uint32 = iota
+ open
+ halfOpen
+)
+
+// Breaker implements the circuit-breaker resiliency pattern
+type Breaker struct {
+ errorThreshold, successThreshold int
+ timeout time.Duration
+
+ lock sync.Mutex
+ state uint32
+ errors, successes int
+ lastError time.Time
+}
+
+// New constructs a new circuit-breaker that starts closed.
+// From closed, the breaker opens if "errorThreshold" errors are seen
+// without an error-free period of at least "timeout". From open, the
+// breaker half-closes after "timeout". From half-open, the breaker closes
+// after "successThreshold" consecutive successes, or opens on a single error.
+func New(errorThreshold, successThreshold int, timeout time.Duration) *Breaker {
+ return &Breaker{
+ errorThreshold: errorThreshold,
+ successThreshold: successThreshold,
+ timeout: timeout,
+ }
+}
+
+// Run will either return ErrBreakerOpen immediately if the circuit-breaker is
+// already open, or it will run the given function and pass along its return
+// value. It is safe to call Run concurrently on the same Breaker.
+func (b *Breaker) Run(work func() error) error {
+ state := atomic.LoadUint32(&b.state)
+
+ if state == open {
+ return ErrBreakerOpen
+ }
+
+ return b.doWork(state, work)
+}
+
+// Go will either return ErrBreakerOpen immediately if the circuit-breaker is
+// already open, or it will run the given function in a separate goroutine.
+// If the function is run, Go will return nil immediately, and will *not* return
+// the return value of the function. It is safe to call Go concurrently on the
+// same Breaker.
+func (b *Breaker) Go(work func() error) error {
+ state := atomic.LoadUint32(&b.state)
+
+ if state == open {
+ return ErrBreakerOpen
+ }
+
+ // errcheck complains about ignoring the error return value, but
+ // that's on purpose; if you want an error from a goroutine you have to
+ // get it over a channel or something
+ go b.doWork(state, work)
+
+ return nil
+}
+
+func (b *Breaker) doWork(state uint32, work func() error) error {
+ var panicValue interface{}
+
+ result := func() error {
+ defer func() {
+ panicValue = recover()
+ }()
+ return work()
+ }()
+
+ if result == nil && panicValue == nil && state == closed {
+ // short-circuit the normal, success path without contending
+ // on the lock
+ return nil
+ }
+
+ // oh well, I guess we have to contend on the lock
+ b.processResult(result, panicValue)
+
+ if panicValue != nil {
+ // as close as Go lets us come to a "rethrow" although unfortunately
+ // we lose the original panicing location
+ panic(panicValue)
+ }
+
+ return result
+}
+
+func (b *Breaker) processResult(result error, panicValue interface{}) {
+ b.lock.Lock()
+ defer b.lock.Unlock()
+
+ if result == nil && panicValue == nil {
+ if b.state == halfOpen {
+ b.successes++
+ if b.successes == b.successThreshold {
+ b.closeBreaker()
+ }
+ }
+ } else {
+ if b.errors > 0 {
+ expiry := b.lastError.Add(b.timeout)
+ if time.Now().After(expiry) {
+ b.errors = 0
+ }
+ }
+
+ switch b.state {
+ case closed:
+ b.errors++
+ if b.errors == b.errorThreshold {
+ b.openBreaker()
+ } else {
+ b.lastError = time.Now()
+ }
+ case halfOpen:
+ b.openBreaker()
+ }
+ }
+}
+
+func (b *Breaker) openBreaker() {
+ b.changeState(open)
+ go b.timer()
+}
+
+func (b *Breaker) closeBreaker() {
+ b.changeState(closed)
+}
+
+func (b *Breaker) timer() {
+ time.Sleep(b.timeout)
+
+ b.lock.Lock()
+ defer b.lock.Unlock()
+
+ b.changeState(halfOpen)
+}
+
+func (b *Breaker) changeState(newState uint32) {
+ b.errors = 0
+ b.successes = 0
+ atomic.StoreUint32(&b.state, newState)
+}