Fix max select series limit for tsi

TSI did not check that the max select series limit during planning
the same way that inmem did.  This means that the limit could be
set but the planning of a high cardinality query would still OOM
the server.  This fixes that limit as well as makes the query interruptible
during planning.
pull/8976/head
Jason Wilder 2017-10-17 15:24:41 -06:00
parent 049a9a859d
commit a6f4069ca7
1 changed files with 20 additions and 0 deletions

View File

@ -747,9 +747,21 @@ func (i *Index) TagSets(name []byte, opt query.IteratorOptions) ([]*query.TagSet
// TagSet are then grouped together, because for the purpose of GROUP BY
// they are part of the same composite series.
tagSets := make(map[string]*query.TagSet, 64)
var seriesN int
if itr != nil {
for e := itr.Next(); e != nil; e = itr.Next() {
// Abort if the query was killed
select {
case <-opt.InterruptCh:
return nil, query.ErrQueryInterrupted
default:
}
if opt.MaxSeriesN > 0 && seriesN > opt.MaxSeriesN {
return nil, fmt.Errorf("max-select-series limit exceeded: (%d/%d)", seriesN, opt.MaxSeriesN)
}
if opt.Authorizer != nil && !opt.Authorizer.AuthorizeSeriesRead(i.Database, name, e.Tags()) {
continue
}
@ -777,11 +789,19 @@ func (i *Index) TagSets(name []byte, opt query.IteratorOptions) ([]*query.TagSet
// Ensure it's back in the map.
tagSets[string(tagsAsKey)] = tagSet
seriesN++
}
}
// Sort the series in each tag set.
for _, t := range tagSets {
// Abort if the query was killed
select {
case <-opt.InterruptCh:
return nil, query.ErrQueryInterrupted
default:
}
sort.Sort(t)
}