youtubebeat/vendor/github.com/elastic/beats/packetbeat/flows/util.go

168 lines
2.8 KiB
Go
Raw Normal View History

2018-11-18 11:08:38 +01:00
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package flows
import (
"sync"
"time"
"github.com/elastic/beats/libbeat/beat"
"github.com/elastic/beats/libbeat/logp"
)
type worker struct {
wg sync.WaitGroup
done chan struct{}
run func(*worker)
}
type spool struct {
pub Reporter
events []beat.Event
}
func newWorker(fn func(w *worker)) *worker {
return &worker{
done: make(chan struct{}),
run: fn,
}
}
func (w *worker) Start() {
debugf("start flows worker")
w.wg.Add(1)
go func() {
defer w.finished()
w.run(w)
}()
}
func (w *worker) Stop() {
debugf("stop flows worker")
close(w.done)
w.wg.Wait()
debugf("stopped flows worker")
}
func (w *worker) finished() {
w.wg.Done()
logp.Info("flows worker loop stopped")
}
func (w *worker) sleep(d time.Duration) bool {
select {
case <-w.done:
return false
case <-time.After(d):
return true
}
}
func (w *worker) tick(t *time.Ticker) bool {
select {
case <-w.done:
return false
case <-t.C:
return true
}
}
func (w *worker) periodically(tick time.Duration, fn func() error) {
defer debugf("stop periodic loop")
ticker := time.NewTicker(tick)
for {
cont := w.tick(ticker)
if !cont {
return
}
err := fn()
if err != nil {
return
}
}
}
func (s *spool) init(pub Reporter, sz int) {
s.pub = pub
s.events = make([]beat.Event, 0, sz)
}
func (s *spool) publish(event beat.Event) {
s.events = append(s.events, event)
if len(s.events) == cap(s.events) {
s.flush()
}
}
func (s *spool) flush() {
if len(s.events) == 0 {
return
}
s.pub(s.events)
s.events = make([]beat.Event, 0, cap(s.events))
}
func gcd(a, b int64) int64 {
if a < 0 || b < 0 {
return 0
}
switch {
case a == b:
return a
case a == 0:
return b
case b == 0:
return a
}
shift := uint(0)
for (a&1) == 0 && (b&1) == 0 {
shift++
a /= 2
b /= 2
}
for (a & 1) == 0 {
a = a / 2
}
// a is always odd
for {
for (b & 1) == 0 {
b = b / 2
}
// both a and b are odd. guaranteed b >= a
if a > b {
a, b = b, a
}
b -= a
if b == 0 {
break
}
}
// restore common factors of 2
return a << shift
}