// 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 }