2018-05-21 21:13:54 +00:00
|
|
|
package execute
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
|
2018-05-21 23:02:42 +00:00
|
|
|
"github.com/influxdata/platform/query"
|
2018-05-21 21:20:06 +00:00
|
|
|
"github.com/influxdata/platform/query/plan"
|
2018-05-21 21:13:54 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// result implements both the Transformation and Result interfaces,
|
|
|
|
// mapping the pushed based Transformation API to the pull based Result interface.
|
|
|
|
type result struct {
|
2018-05-24 17:29:36 +00:00
|
|
|
name string
|
|
|
|
|
2018-05-21 21:13:54 +00:00
|
|
|
mu sync.Mutex
|
|
|
|
blocks chan resultMessage
|
|
|
|
|
|
|
|
abortErr chan error
|
|
|
|
aborted chan struct{}
|
|
|
|
}
|
|
|
|
|
|
|
|
type resultMessage struct {
|
2018-05-21 23:02:42 +00:00
|
|
|
block query.Block
|
2018-05-21 21:13:54 +00:00
|
|
|
err error
|
|
|
|
}
|
|
|
|
|
2018-05-24 17:29:36 +00:00
|
|
|
func newResult(name string, spec plan.YieldSpec) *result {
|
2018-05-21 21:13:54 +00:00
|
|
|
return &result{
|
2018-05-24 17:29:36 +00:00
|
|
|
name: name,
|
2018-05-21 21:13:54 +00:00
|
|
|
// TODO(nathanielc): Currently this buffer needs to be big enough hold all result blocks :(
|
|
|
|
blocks: make(chan resultMessage, 1000),
|
|
|
|
abortErr: make(chan error, 1),
|
|
|
|
aborted: make(chan struct{}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 17:29:36 +00:00
|
|
|
func (s *result) Name() string {
|
|
|
|
return s.name
|
|
|
|
}
|
2018-05-21 23:02:42 +00:00
|
|
|
func (s *result) RetractBlock(DatasetID, query.PartitionKey) error {
|
2018-05-21 21:13:54 +00:00
|
|
|
//TODO implement
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-05-21 23:02:42 +00:00
|
|
|
func (s *result) Process(id DatasetID, b query.Block) error {
|
2018-05-21 21:13:54 +00:00
|
|
|
select {
|
|
|
|
case s.blocks <- resultMessage{
|
|
|
|
block: b,
|
|
|
|
}:
|
|
|
|
case <-s.aborted:
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-05-21 23:02:42 +00:00
|
|
|
func (s *result) Blocks() query.BlockIterator {
|
2018-05-21 21:13:54 +00:00
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2018-05-21 23:02:42 +00:00
|
|
|
func (s *result) Do(f func(query.Block) error) error {
|
2018-05-21 21:13:54 +00:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case err := <-s.abortErr:
|
|
|
|
return err
|
|
|
|
case msg, more := <-s.blocks:
|
|
|
|
if !more {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if msg.err != nil {
|
|
|
|
return msg.err
|
|
|
|
}
|
|
|
|
if err := f(msg.block); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *result) UpdateWatermark(id DatasetID, mark Time) error {
|
|
|
|
//Nothing to do
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
func (s *result) UpdateProcessingTime(id DatasetID, t Time) error {
|
|
|
|
//Nothing to do
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *result) setTrigger(Trigger) {
|
|
|
|
//TODO: Change interfaces so that resultSink, does not need to implement this method.
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *result) Finish(id DatasetID, err error) {
|
|
|
|
if err != nil {
|
|
|
|
select {
|
|
|
|
case s.blocks <- resultMessage{
|
|
|
|
err: err,
|
|
|
|
}:
|
|
|
|
case <-s.aborted:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close(s.blocks)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Abort the result with the given error
|
|
|
|
func (s *result) abort(err error) {
|
|
|
|
s.mu.Lock()
|
|
|
|
defer s.mu.Unlock()
|
|
|
|
|
|
|
|
// Check if we have already aborted
|
|
|
|
aborted := false
|
|
|
|
select {
|
|
|
|
case <-s.aborted:
|
|
|
|
aborted = true
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
if aborted {
|
|
|
|
return // already aborted
|
|
|
|
}
|
|
|
|
|
|
|
|
s.abortErr <- err
|
|
|
|
close(s.aborted)
|
|
|
|
}
|