1// Generated by tmpl 2// https://github.com/benbjohnson/tmpl 3// 4// DO NOT EDIT! 5// Source: iterator.gen.go.tmpl 6 7package query 8 9import ( 10 "container/heap" 11 "context" 12 "io" 13 "sort" 14 "sync" 15 "time" 16 17 "github.com/gogo/protobuf/proto" 18 "github.com/influxdata/influxql" 19) 20 21// DefaultStatsInterval is the default value for IteratorEncoder.StatsInterval. 22const DefaultStatsInterval = time.Second 23 24// FloatIterator represents a stream of float points. 25type FloatIterator interface { 26 Iterator 27 Next() (*FloatPoint, error) 28} 29 30// newFloatIterators converts a slice of Iterator to a slice of FloatIterator. 31// Drop and closes any iterator in itrs that is not a FloatIterator and cannot 32// be cast to a FloatIterator. 33func newFloatIterators(itrs []Iterator) []FloatIterator { 34 a := make([]FloatIterator, 0, len(itrs)) 35 for _, itr := range itrs { 36 switch itr := itr.(type) { 37 case FloatIterator: 38 a = append(a, itr) 39 default: 40 itr.Close() 41 } 42 } 43 return a 44} 45 46// bufFloatIterator represents a buffered FloatIterator. 47type bufFloatIterator struct { 48 itr FloatIterator 49 buf *FloatPoint 50} 51 52// newBufFloatIterator returns a buffered FloatIterator. 53func newBufFloatIterator(itr FloatIterator) *bufFloatIterator { 54 return &bufFloatIterator{itr: itr} 55} 56 57// Stats returns statistics from the input iterator. 58func (itr *bufFloatIterator) Stats() IteratorStats { return itr.itr.Stats() } 59 60// Close closes the underlying iterator. 61func (itr *bufFloatIterator) Close() error { return itr.itr.Close() } 62 63// peek returns the next point without removing it from the iterator. 64func (itr *bufFloatIterator) peek() (*FloatPoint, error) { 65 p, err := itr.Next() 66 if err != nil { 67 return nil, err 68 } 69 itr.unread(p) 70 return p, nil 71} 72 73// peekTime returns the time of the next point. 74// Returns zero time if no more points available. 75func (itr *bufFloatIterator) peekTime() (int64, error) { 76 p, err := itr.peek() 77 if p == nil || err != nil { 78 return ZeroTime, err 79 } 80 return p.Time, nil 81} 82 83// Next returns the current buffer, if exists, or calls the underlying iterator. 84func (itr *bufFloatIterator) Next() (*FloatPoint, error) { 85 buf := itr.buf 86 if buf != nil { 87 itr.buf = nil 88 return buf, nil 89 } 90 return itr.itr.Next() 91} 92 93// NextInWindow returns the next value if it is between [startTime, endTime). 94// If the next value is outside the range then it is moved to the buffer. 95func (itr *bufFloatIterator) NextInWindow(startTime, endTime int64) (*FloatPoint, error) { 96 v, err := itr.Next() 97 if v == nil || err != nil { 98 return nil, err 99 } else if t := v.Time; t >= endTime || t < startTime { 100 itr.unread(v) 101 return nil, nil 102 } 103 return v, nil 104} 105 106// unread sets v to the buffer. It is read on the next call to Next(). 107func (itr *bufFloatIterator) unread(v *FloatPoint) { itr.buf = v } 108 109// floatMergeIterator represents an iterator that combines multiple float iterators. 110type floatMergeIterator struct { 111 inputs []FloatIterator 112 heap *floatMergeHeap 113 init bool 114 115 closed bool 116 mu sync.RWMutex 117 118 // Current iterator and window. 119 curr *floatMergeHeapItem 120 window struct { 121 name string 122 tags string 123 startTime int64 124 endTime int64 125 } 126} 127 128// newFloatMergeIterator returns a new instance of floatMergeIterator. 129func newFloatMergeIterator(inputs []FloatIterator, opt IteratorOptions) *floatMergeIterator { 130 itr := &floatMergeIterator{ 131 inputs: inputs, 132 heap: &floatMergeHeap{ 133 items: make([]*floatMergeHeapItem, 0, len(inputs)), 134 opt: opt, 135 }, 136 } 137 138 // Initialize heap items. 139 for _, input := range inputs { 140 // Wrap in buffer, ignore any inputs without anymore points. 141 bufInput := newBufFloatIterator(input) 142 143 // Append to the heap. 144 itr.heap.items = append(itr.heap.items, &floatMergeHeapItem{itr: bufInput}) 145 } 146 147 return itr 148} 149 150// Stats returns an aggregation of stats from the underlying iterators. 151func (itr *floatMergeIterator) Stats() IteratorStats { 152 var stats IteratorStats 153 for _, input := range itr.inputs { 154 stats.Add(input.Stats()) 155 } 156 return stats 157} 158 159// Close closes the underlying iterators. 160func (itr *floatMergeIterator) Close() error { 161 itr.mu.Lock() 162 defer itr.mu.Unlock() 163 164 for _, input := range itr.inputs { 165 input.Close() 166 } 167 itr.curr = nil 168 itr.inputs = nil 169 itr.heap.items = nil 170 itr.closed = true 171 return nil 172} 173 174// Next returns the next point from the iterator. 175func (itr *floatMergeIterator) Next() (*FloatPoint, error) { 176 itr.mu.RLock() 177 defer itr.mu.RUnlock() 178 if itr.closed { 179 return nil, nil 180 } 181 182 // Initialize the heap. This needs to be done lazily on the first call to this iterator 183 // so that iterator initialization done through the Select() call returns quickly. 184 // Queries can only be interrupted after the Select() call completes so any operations 185 // done during iterator creation cannot be interrupted, which is why we do it here 186 // instead so an interrupt can happen while initializing the heap. 187 if !itr.init { 188 items := itr.heap.items 189 itr.heap.items = make([]*floatMergeHeapItem, 0, len(items)) 190 for _, item := range items { 191 if p, err := item.itr.peek(); err != nil { 192 return nil, err 193 } else if p == nil { 194 continue 195 } 196 itr.heap.items = append(itr.heap.items, item) 197 } 198 heap.Init(itr.heap) 199 itr.init = true 200 } 201 202 for { 203 // Retrieve the next iterator if we don't have one. 204 if itr.curr == nil { 205 if len(itr.heap.items) == 0 { 206 return nil, nil 207 } 208 itr.curr = heap.Pop(itr.heap).(*floatMergeHeapItem) 209 210 // Read point and set current window. 211 p, err := itr.curr.itr.Next() 212 if err != nil { 213 return nil, err 214 } 215 tags := p.Tags.Subset(itr.heap.opt.Dimensions) 216 itr.window.name, itr.window.tags = p.Name, tags.ID() 217 itr.window.startTime, itr.window.endTime = itr.heap.opt.Window(p.Time) 218 return p, nil 219 } 220 221 // Read the next point from the current iterator. 222 p, err := itr.curr.itr.Next() 223 if err != nil { 224 return nil, err 225 } 226 227 // If there are no more points then remove iterator from heap and find next. 228 if p == nil { 229 itr.curr = nil 230 continue 231 } 232 233 // Check if the point is inside of our current window. 234 inWindow := true 235 if window := itr.window; window.name != p.Name { 236 inWindow = false 237 } else if tags := p.Tags.Subset(itr.heap.opt.Dimensions); window.tags != tags.ID() { 238 inWindow = false 239 } else if opt := itr.heap.opt; opt.Ascending && p.Time >= window.endTime { 240 inWindow = false 241 } else if !opt.Ascending && p.Time < window.startTime { 242 inWindow = false 243 } 244 245 // If it's outside our window then push iterator back on the heap and find new iterator. 246 if !inWindow { 247 itr.curr.itr.unread(p) 248 heap.Push(itr.heap, itr.curr) 249 itr.curr = nil 250 continue 251 } 252 253 return p, nil 254 } 255} 256 257// floatMergeHeap represents a heap of floatMergeHeapItems. 258// Items are sorted by their next window and then by name/tags. 259type floatMergeHeap struct { 260 opt IteratorOptions 261 items []*floatMergeHeapItem 262} 263 264func (h *floatMergeHeap) Len() int { return len(h.items) } 265func (h *floatMergeHeap) Swap(i, j int) { h.items[i], h.items[j] = h.items[j], h.items[i] } 266func (h *floatMergeHeap) Less(i, j int) bool { 267 x, err := h.items[i].itr.peek() 268 if err != nil { 269 return true 270 } 271 y, err := h.items[j].itr.peek() 272 if err != nil { 273 return false 274 } 275 276 if h.opt.Ascending { 277 if x.Name != y.Name { 278 return x.Name < y.Name 279 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); xTags.ID() != yTags.ID() { 280 return xTags.ID() < yTags.ID() 281 } 282 } else { 283 if x.Name != y.Name { 284 return x.Name > y.Name 285 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); xTags.ID() != yTags.ID() { 286 return xTags.ID() > yTags.ID() 287 } 288 } 289 290 xt, _ := h.opt.Window(x.Time) 291 yt, _ := h.opt.Window(y.Time) 292 293 if h.opt.Ascending { 294 return xt < yt 295 } 296 return xt > yt 297} 298 299func (h *floatMergeHeap) Push(x interface{}) { 300 h.items = append(h.items, x.(*floatMergeHeapItem)) 301} 302 303func (h *floatMergeHeap) Pop() interface{} { 304 old := h.items 305 n := len(old) 306 item := old[n-1] 307 h.items = old[0 : n-1] 308 return item 309} 310 311type floatMergeHeapItem struct { 312 itr *bufFloatIterator 313} 314 315// floatSortedMergeIterator is an iterator that sorts and merges multiple iterators into one. 316type floatSortedMergeIterator struct { 317 inputs []FloatIterator 318 heap *floatSortedMergeHeap 319 init bool 320} 321 322// newFloatSortedMergeIterator returns an instance of floatSortedMergeIterator. 323func newFloatSortedMergeIterator(inputs []FloatIterator, opt IteratorOptions) Iterator { 324 itr := &floatSortedMergeIterator{ 325 inputs: inputs, 326 heap: &floatSortedMergeHeap{ 327 items: make([]*floatSortedMergeHeapItem, 0, len(inputs)), 328 opt: opt, 329 }, 330 } 331 332 // Initialize heap items. 333 for _, input := range inputs { 334 // Append to the heap. 335 itr.heap.items = append(itr.heap.items, &floatSortedMergeHeapItem{itr: input}) 336 } 337 338 return itr 339} 340 341// Stats returns an aggregation of stats from the underlying iterators. 342func (itr *floatSortedMergeIterator) Stats() IteratorStats { 343 var stats IteratorStats 344 for _, input := range itr.inputs { 345 stats.Add(input.Stats()) 346 } 347 return stats 348} 349 350// Close closes the underlying iterators. 351func (itr *floatSortedMergeIterator) Close() error { 352 for _, input := range itr.inputs { 353 input.Close() 354 } 355 return nil 356} 357 358// Next returns the next points from the iterator. 359func (itr *floatSortedMergeIterator) Next() (*FloatPoint, error) { return itr.pop() } 360 361// pop returns the next point from the heap. 362// Reads the next point from item's cursor and puts it back on the heap. 363func (itr *floatSortedMergeIterator) pop() (*FloatPoint, error) { 364 // Initialize the heap. See the MergeIterator to see why this has to be done lazily. 365 if !itr.init { 366 items := itr.heap.items 367 itr.heap.items = make([]*floatSortedMergeHeapItem, 0, len(items)) 368 for _, item := range items { 369 var err error 370 if item.point, err = item.itr.Next(); err != nil { 371 return nil, err 372 } else if item.point == nil { 373 continue 374 } 375 itr.heap.items = append(itr.heap.items, item) 376 } 377 heap.Init(itr.heap) 378 itr.init = true 379 } 380 381 if len(itr.heap.items) == 0 { 382 return nil, nil 383 } 384 385 // Read the next item from the heap. 386 item := heap.Pop(itr.heap).(*floatSortedMergeHeapItem) 387 if item.err != nil { 388 return nil, item.err 389 } else if item.point == nil { 390 return nil, nil 391 } 392 393 // Copy the point for return. 394 p := item.point.Clone() 395 396 // Read the next item from the cursor. Push back to heap if one exists. 397 if item.point, item.err = item.itr.Next(); item.point != nil { 398 heap.Push(itr.heap, item) 399 } 400 401 return p, nil 402} 403 404// floatSortedMergeHeap represents a heap of floatSortedMergeHeapItems. 405// Items are sorted with the following priority: 406// - By their measurement name; 407// - By their tag keys/values; 408// - By time; or 409// - By their Aux field values. 410// 411type floatSortedMergeHeap struct { 412 opt IteratorOptions 413 items []*floatSortedMergeHeapItem 414} 415 416func (h *floatSortedMergeHeap) Len() int { return len(h.items) } 417func (h *floatSortedMergeHeap) Swap(i, j int) { h.items[i], h.items[j] = h.items[j], h.items[i] } 418func (h *floatSortedMergeHeap) Less(i, j int) bool { 419 x, y := h.items[i].point, h.items[j].point 420 421 if h.opt.Ascending { 422 if x.Name != y.Name { 423 return x.Name < y.Name 424 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); !xTags.Equals(&yTags) { 425 return xTags.ID() < yTags.ID() 426 } 427 428 if x.Time != y.Time { 429 return x.Time < y.Time 430 } 431 432 if len(x.Aux) > 0 && len(x.Aux) == len(y.Aux) { 433 for i := 0; i < len(x.Aux); i++ { 434 v1, ok1 := x.Aux[i].(string) 435 v2, ok2 := y.Aux[i].(string) 436 if !ok1 || !ok2 { 437 // Unsupported types used in Aux fields. Maybe they 438 // need to be added here? 439 return false 440 } else if v1 == v2 { 441 continue 442 } 443 return v1 < v2 444 } 445 } 446 return false // Times and/or Aux fields are equal. 447 } 448 449 if x.Name != y.Name { 450 return x.Name > y.Name 451 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); !xTags.Equals(&yTags) { 452 return xTags.ID() > yTags.ID() 453 } 454 455 if x.Time != y.Time { 456 return x.Time > y.Time 457 } 458 459 if len(x.Aux) > 0 && len(x.Aux) == len(y.Aux) { 460 for i := 0; i < len(x.Aux); i++ { 461 v1, ok1 := x.Aux[i].(string) 462 v2, ok2 := y.Aux[i].(string) 463 if !ok1 || !ok2 { 464 // Unsupported types used in Aux fields. Maybe they 465 // need to be added here? 466 return false 467 } else if v1 == v2 { 468 continue 469 } 470 return v1 > v2 471 } 472 } 473 return false // Times and/or Aux fields are equal. 474} 475 476func (h *floatSortedMergeHeap) Push(x interface{}) { 477 h.items = append(h.items, x.(*floatSortedMergeHeapItem)) 478} 479 480func (h *floatSortedMergeHeap) Pop() interface{} { 481 old := h.items 482 n := len(old) 483 item := old[n-1] 484 h.items = old[0 : n-1] 485 return item 486} 487 488type floatSortedMergeHeapItem struct { 489 point *FloatPoint 490 err error 491 itr FloatIterator 492} 493 494// floatIteratorScanner scans the results of a FloatIterator into a map. 495type floatIteratorScanner struct { 496 input *bufFloatIterator 497 err error 498 keys []influxql.VarRef 499 defaultValue interface{} 500} 501 502// newFloatIteratorScanner creates a new IteratorScanner. 503func newFloatIteratorScanner(input FloatIterator, keys []influxql.VarRef, defaultValue interface{}) *floatIteratorScanner { 504 return &floatIteratorScanner{ 505 input: newBufFloatIterator(input), 506 keys: keys, 507 defaultValue: defaultValue, 508 } 509} 510 511func (s *floatIteratorScanner) Peek() (int64, string, Tags) { 512 if s.err != nil { 513 return ZeroTime, "", Tags{} 514 } 515 516 p, err := s.input.peek() 517 if err != nil { 518 s.err = err 519 return ZeroTime, "", Tags{} 520 } else if p == nil { 521 return ZeroTime, "", Tags{} 522 } 523 return p.Time, p.Name, p.Tags 524} 525 526func (s *floatIteratorScanner) ScanAt(ts int64, name string, tags Tags, m map[string]interface{}) { 527 if s.err != nil { 528 return 529 } 530 531 p, err := s.input.Next() 532 if err != nil { 533 s.err = err 534 return 535 } else if p == nil { 536 s.useDefaults(m) 537 return 538 } else if p.Time != ts || p.Name != name || !p.Tags.Equals(&tags) { 539 s.useDefaults(m) 540 s.input.unread(p) 541 return 542 } 543 544 if k := s.keys[0]; k.Val != "" { 545 if p.Nil { 546 if s.defaultValue != SkipDefault { 547 m[k.Val] = castToType(s.defaultValue, k.Type) 548 } 549 } else { 550 m[k.Val] = p.Value 551 } 552 } 553 for i, v := range p.Aux { 554 k := s.keys[i+1] 555 switch v.(type) { 556 case float64, int64, uint64, string, bool: 557 m[k.Val] = v 558 default: 559 // Insert the fill value if one was specified. 560 if s.defaultValue != SkipDefault { 561 m[k.Val] = castToType(s.defaultValue, k.Type) 562 } 563 } 564 } 565} 566 567func (s *floatIteratorScanner) useDefaults(m map[string]interface{}) { 568 if s.defaultValue == SkipDefault { 569 return 570 } 571 for _, k := range s.keys { 572 if k.Val == "" { 573 continue 574 } 575 m[k.Val] = castToType(s.defaultValue, k.Type) 576 } 577} 578 579func (s *floatIteratorScanner) Stats() IteratorStats { return s.input.Stats() } 580func (s *floatIteratorScanner) Err() error { return s.err } 581func (s *floatIteratorScanner) Close() error { return s.input.Close() } 582 583// floatParallelIterator represents an iterator that pulls data in a separate goroutine. 584type floatParallelIterator struct { 585 input FloatIterator 586 ch chan floatPointError 587 588 once sync.Once 589 closing chan struct{} 590 wg sync.WaitGroup 591} 592 593// newFloatParallelIterator returns a new instance of floatParallelIterator. 594func newFloatParallelIterator(input FloatIterator) *floatParallelIterator { 595 itr := &floatParallelIterator{ 596 input: input, 597 ch: make(chan floatPointError, 256), 598 closing: make(chan struct{}), 599 } 600 itr.wg.Add(1) 601 go itr.monitor() 602 return itr 603} 604 605// Stats returns stats from the underlying iterator. 606func (itr *floatParallelIterator) Stats() IteratorStats { return itr.input.Stats() } 607 608// Close closes the underlying iterators. 609func (itr *floatParallelIterator) Close() error { 610 itr.once.Do(func() { close(itr.closing) }) 611 itr.wg.Wait() 612 return itr.input.Close() 613} 614 615// Next returns the next point from the iterator. 616func (itr *floatParallelIterator) Next() (*FloatPoint, error) { 617 v, ok := <-itr.ch 618 if !ok { 619 return nil, io.EOF 620 } 621 return v.point, v.err 622} 623 624// monitor runs in a separate goroutine and actively pulls the next point. 625func (itr *floatParallelIterator) monitor() { 626 defer close(itr.ch) 627 defer itr.wg.Done() 628 629 for { 630 // Read next point. 631 p, err := itr.input.Next() 632 if p != nil { 633 p = p.Clone() 634 } 635 636 select { 637 case <-itr.closing: 638 return 639 case itr.ch <- floatPointError{point: p, err: err}: 640 } 641 } 642} 643 644type floatPointError struct { 645 point *FloatPoint 646 err error 647} 648 649// floatLimitIterator represents an iterator that limits points per group. 650type floatLimitIterator struct { 651 input FloatIterator 652 opt IteratorOptions 653 n int 654 655 prev struct { 656 name string 657 tags Tags 658 } 659} 660 661// newFloatLimitIterator returns a new instance of floatLimitIterator. 662func newFloatLimitIterator(input FloatIterator, opt IteratorOptions) *floatLimitIterator { 663 return &floatLimitIterator{ 664 input: input, 665 opt: opt, 666 } 667} 668 669// Stats returns stats from the underlying iterator. 670func (itr *floatLimitIterator) Stats() IteratorStats { return itr.input.Stats() } 671 672// Close closes the underlying iterators. 673func (itr *floatLimitIterator) Close() error { return itr.input.Close() } 674 675// Next returns the next point from the iterator. 676func (itr *floatLimitIterator) Next() (*FloatPoint, error) { 677 for { 678 p, err := itr.input.Next() 679 if p == nil || err != nil { 680 return nil, err 681 } 682 683 // Reset window and counter if a new window is encountered. 684 if p.Name != itr.prev.name || !p.Tags.Equals(&itr.prev.tags) { 685 itr.prev.name = p.Name 686 itr.prev.tags = p.Tags 687 itr.n = 0 688 } 689 690 // Increment counter. 691 itr.n++ 692 693 // Read next point if not beyond the offset. 694 if itr.n <= itr.opt.Offset { 695 continue 696 } 697 698 // Read next point if we're beyond the limit. 699 if itr.opt.Limit > 0 && (itr.n-itr.opt.Offset) > itr.opt.Limit { 700 continue 701 } 702 703 return p, nil 704 } 705} 706 707type floatFillIterator struct { 708 input *bufFloatIterator 709 prev FloatPoint 710 startTime int64 711 endTime int64 712 auxFields []interface{} 713 init bool 714 opt IteratorOptions 715 716 window struct { 717 name string 718 tags Tags 719 time int64 720 offset int64 721 } 722} 723 724func newFloatFillIterator(input FloatIterator, expr influxql.Expr, opt IteratorOptions) *floatFillIterator { 725 if opt.Fill == influxql.NullFill { 726 if expr, ok := expr.(*influxql.Call); ok && expr.Name == "count" { 727 opt.Fill = influxql.NumberFill 728 opt.FillValue = float64(0) 729 } 730 } 731 732 var startTime, endTime int64 733 if opt.Ascending { 734 startTime, _ = opt.Window(opt.StartTime) 735 endTime, _ = opt.Window(opt.EndTime) 736 } else { 737 startTime, _ = opt.Window(opt.EndTime) 738 endTime, _ = opt.Window(opt.StartTime) 739 } 740 741 var auxFields []interface{} 742 if len(opt.Aux) > 0 { 743 auxFields = make([]interface{}, len(opt.Aux)) 744 } 745 746 return &floatFillIterator{ 747 input: newBufFloatIterator(input), 748 prev: FloatPoint{Nil: true}, 749 startTime: startTime, 750 endTime: endTime, 751 auxFields: auxFields, 752 opt: opt, 753 } 754} 755 756func (itr *floatFillIterator) Stats() IteratorStats { return itr.input.Stats() } 757func (itr *floatFillIterator) Close() error { return itr.input.Close() } 758 759func (itr *floatFillIterator) Next() (*FloatPoint, error) { 760 if !itr.init { 761 p, err := itr.input.peek() 762 if p == nil || err != nil { 763 return nil, err 764 } 765 itr.window.name, itr.window.tags = p.Name, p.Tags 766 itr.window.time = itr.startTime 767 if itr.startTime == influxql.MinTime { 768 itr.window.time, _ = itr.opt.Window(p.Time) 769 } 770 if itr.opt.Location != nil { 771 _, itr.window.offset = itr.opt.Zone(itr.window.time) 772 } 773 itr.init = true 774 } 775 776 p, err := itr.input.Next() 777 if err != nil { 778 return nil, err 779 } 780 781 // Check if the next point is outside of our window or is nil. 782 if p == nil || p.Name != itr.window.name || p.Tags.ID() != itr.window.tags.ID() { 783 // If we are inside of an interval, unread the point and continue below to 784 // constructing a new point. 785 if itr.opt.Ascending && itr.window.time <= itr.endTime { 786 itr.input.unread(p) 787 p = nil 788 goto CONSTRUCT 789 } else if !itr.opt.Ascending && itr.window.time >= itr.endTime && itr.endTime != influxql.MinTime { 790 itr.input.unread(p) 791 p = nil 792 goto CONSTRUCT 793 } 794 795 // We are *not* in a current interval. If there is no next point, 796 // we are at the end of all intervals. 797 if p == nil { 798 return nil, nil 799 } 800 801 // Set the new interval. 802 itr.window.name, itr.window.tags = p.Name, p.Tags 803 itr.window.time = itr.startTime 804 if itr.window.time == influxql.MinTime { 805 itr.window.time, _ = itr.opt.Window(p.Time) 806 } 807 if itr.opt.Location != nil { 808 _, itr.window.offset = itr.opt.Zone(itr.window.time) 809 } 810 itr.prev = FloatPoint{Nil: true} 811 } 812 813 // Check if the point is our next expected point. 814CONSTRUCT: 815 if p == nil || (itr.opt.Ascending && p.Time > itr.window.time) || (!itr.opt.Ascending && p.Time < itr.window.time) { 816 if p != nil { 817 itr.input.unread(p) 818 } 819 820 p = &FloatPoint{ 821 Name: itr.window.name, 822 Tags: itr.window.tags, 823 Time: itr.window.time, 824 Aux: itr.auxFields, 825 } 826 827 switch itr.opt.Fill { 828 case influxql.LinearFill: 829 if !itr.prev.Nil { 830 next, err := itr.input.peek() 831 if err != nil { 832 return nil, err 833 } else if next != nil && next.Name == itr.window.name && next.Tags.ID() == itr.window.tags.ID() { 834 interval := int64(itr.opt.Interval.Duration) 835 start := itr.window.time / interval 836 p.Value = linearFloat(start, itr.prev.Time/interval, next.Time/interval, itr.prev.Value, next.Value) 837 } else { 838 p.Nil = true 839 } 840 } else { 841 p.Nil = true 842 } 843 844 case influxql.NullFill: 845 p.Nil = true 846 case influxql.NumberFill: 847 p.Value, _ = castToFloat(itr.opt.FillValue) 848 case influxql.PreviousFill: 849 if !itr.prev.Nil { 850 p.Value = itr.prev.Value 851 p.Nil = itr.prev.Nil 852 } else { 853 p.Nil = true 854 } 855 } 856 } else { 857 itr.prev = *p 858 } 859 860 // Advance the expected time. Do not advance to a new window here 861 // as there may be lingering points with the same timestamp in the previous 862 // window. 863 if itr.opt.Ascending { 864 itr.window.time += int64(itr.opt.Interval.Duration) 865 } else { 866 itr.window.time -= int64(itr.opt.Interval.Duration) 867 } 868 869 // Check to see if we have passed over an offset change and adjust the time 870 // to account for this new offset. 871 if itr.opt.Location != nil { 872 if _, offset := itr.opt.Zone(itr.window.time - 1); offset != itr.window.offset { 873 diff := itr.window.offset - offset 874 if abs(diff) < int64(itr.opt.Interval.Duration) { 875 itr.window.time += diff 876 } 877 itr.window.offset = offset 878 } 879 } 880 return p, nil 881} 882 883// floatIntervalIterator represents a float implementation of IntervalIterator. 884type floatIntervalIterator struct { 885 input FloatIterator 886 opt IteratorOptions 887} 888 889func newFloatIntervalIterator(input FloatIterator, opt IteratorOptions) *floatIntervalIterator { 890 return &floatIntervalIterator{input: input, opt: opt} 891} 892 893func (itr *floatIntervalIterator) Stats() IteratorStats { return itr.input.Stats() } 894func (itr *floatIntervalIterator) Close() error { return itr.input.Close() } 895 896func (itr *floatIntervalIterator) Next() (*FloatPoint, error) { 897 p, err := itr.input.Next() 898 if p == nil || err != nil { 899 return nil, err 900 } 901 p.Time, _ = itr.opt.Window(p.Time) 902 // If we see the minimum allowable time, set the time to zero so we don't 903 // break the default returned time for aggregate queries without times. 904 if p.Time == influxql.MinTime { 905 p.Time = 0 906 } 907 return p, nil 908} 909 910// floatInterruptIterator represents a float implementation of InterruptIterator. 911type floatInterruptIterator struct { 912 input FloatIterator 913 closing <-chan struct{} 914 count int 915} 916 917func newFloatInterruptIterator(input FloatIterator, closing <-chan struct{}) *floatInterruptIterator { 918 return &floatInterruptIterator{input: input, closing: closing} 919} 920 921func (itr *floatInterruptIterator) Stats() IteratorStats { return itr.input.Stats() } 922func (itr *floatInterruptIterator) Close() error { return itr.input.Close() } 923 924func (itr *floatInterruptIterator) Next() (*FloatPoint, error) { 925 // Only check if the channel is closed every N points. This 926 // intentionally checks on both 0 and N so that if the iterator 927 // has been interrupted before the first point is emitted it will 928 // not emit any points. 929 if itr.count&0xFF == 0xFF { 930 select { 931 case <-itr.closing: 932 return nil, itr.Close() 933 default: 934 // Reset iterator count to zero and fall through to emit the next point. 935 itr.count = 0 936 } 937 } 938 939 // Increment the counter for every point read. 940 itr.count++ 941 return itr.input.Next() 942} 943 944// floatCloseInterruptIterator represents a float implementation of CloseInterruptIterator. 945type floatCloseInterruptIterator struct { 946 input FloatIterator 947 closing <-chan struct{} 948 done chan struct{} 949 once sync.Once 950} 951 952func newFloatCloseInterruptIterator(input FloatIterator, closing <-chan struct{}) *floatCloseInterruptIterator { 953 itr := &floatCloseInterruptIterator{ 954 input: input, 955 closing: closing, 956 done: make(chan struct{}), 957 } 958 go itr.monitor() 959 return itr 960} 961 962func (itr *floatCloseInterruptIterator) monitor() { 963 select { 964 case <-itr.closing: 965 itr.Close() 966 case <-itr.done: 967 } 968} 969 970func (itr *floatCloseInterruptIterator) Stats() IteratorStats { 971 return itr.input.Stats() 972} 973 974func (itr *floatCloseInterruptIterator) Close() error { 975 itr.once.Do(func() { 976 close(itr.done) 977 itr.input.Close() 978 }) 979 return nil 980} 981 982func (itr *floatCloseInterruptIterator) Next() (*FloatPoint, error) { 983 p, err := itr.input.Next() 984 if err != nil { 985 // Check if the iterator was closed. 986 select { 987 case <-itr.done: 988 return nil, nil 989 default: 990 return nil, err 991 } 992 } 993 return p, nil 994} 995 996// floatReduceFloatIterator executes a reducer for every interval and buffers the result. 997type floatReduceFloatIterator struct { 998 input *bufFloatIterator 999 create func() (FloatPointAggregator, FloatPointEmitter) 1000 dims []string 1001 opt IteratorOptions 1002 points []FloatPoint 1003 keepTags bool 1004} 1005 1006func newFloatReduceFloatIterator(input FloatIterator, opt IteratorOptions, createFn func() (FloatPointAggregator, FloatPointEmitter)) *floatReduceFloatIterator { 1007 return &floatReduceFloatIterator{ 1008 input: newBufFloatIterator(input), 1009 create: createFn, 1010 dims: opt.GetDimensions(), 1011 opt: opt, 1012 } 1013} 1014 1015// Stats returns stats from the input iterator. 1016func (itr *floatReduceFloatIterator) Stats() IteratorStats { return itr.input.Stats() } 1017 1018// Close closes the iterator and all child iterators. 1019func (itr *floatReduceFloatIterator) Close() error { return itr.input.Close() } 1020 1021// Next returns the minimum value for the next available interval. 1022func (itr *floatReduceFloatIterator) Next() (*FloatPoint, error) { 1023 // Calculate next window if we have no more points. 1024 if len(itr.points) == 0 { 1025 var err error 1026 itr.points, err = itr.reduce() 1027 if len(itr.points) == 0 { 1028 return nil, err 1029 } 1030 } 1031 1032 // Pop next point off the stack. 1033 p := &itr.points[len(itr.points)-1] 1034 itr.points = itr.points[:len(itr.points)-1] 1035 return p, nil 1036} 1037 1038// floatReduceFloatPoint stores the reduced data for a name/tag combination. 1039type floatReduceFloatPoint struct { 1040 Name string 1041 Tags Tags 1042 Aggregator FloatPointAggregator 1043 Emitter FloatPointEmitter 1044} 1045 1046// reduce executes fn once for every point in the next window. 1047// The previous value for the dimension is passed to fn. 1048func (itr *floatReduceFloatIterator) reduce() ([]FloatPoint, error) { 1049 // Calculate next window. 1050 var ( 1051 startTime, endTime int64 1052 window struct { 1053 name string 1054 tags string 1055 } 1056 ) 1057 for { 1058 p, err := itr.input.Next() 1059 if err != nil || p == nil { 1060 return nil, err 1061 } else if p.Nil { 1062 continue 1063 } 1064 1065 // Unread the point so it can be processed. 1066 itr.input.unread(p) 1067 startTime, endTime = itr.opt.Window(p.Time) 1068 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 1069 break 1070 } 1071 1072 // Create points by tags. 1073 m := make(map[string]*floatReduceFloatPoint) 1074 for { 1075 // Read next point. 1076 curr, err := itr.input.NextInWindow(startTime, endTime) 1077 if err != nil { 1078 return nil, err 1079 } else if curr == nil { 1080 break 1081 } else if curr.Nil { 1082 continue 1083 } else if curr.Name != window.name { 1084 itr.input.unread(curr) 1085 break 1086 } 1087 1088 // Ensure this point is within the same final window. 1089 if curr.Name != window.name { 1090 itr.input.unread(curr) 1091 break 1092 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 1093 itr.input.unread(curr) 1094 break 1095 } 1096 1097 // Retrieve the tags on this point for this level of the query. 1098 // This may be different than the bucket dimensions. 1099 tags := curr.Tags.Subset(itr.dims) 1100 id := tags.ID() 1101 1102 // Retrieve the aggregator for this name/tag combination or create one. 1103 rp := m[id] 1104 if rp == nil { 1105 aggregator, emitter := itr.create() 1106 rp = &floatReduceFloatPoint{ 1107 Name: curr.Name, 1108 Tags: tags, 1109 Aggregator: aggregator, 1110 Emitter: emitter, 1111 } 1112 m[id] = rp 1113 } 1114 rp.Aggregator.AggregateFloat(curr) 1115 } 1116 1117 keys := make([]string, 0, len(m)) 1118 for k := range m { 1119 keys = append(keys, k) 1120 } 1121 1122 // Reverse sort points by name & tag. 1123 // This ensures a consistent order of output. 1124 if len(keys) > 0 { 1125 var sorted sort.Interface = sort.StringSlice(keys) 1126 if itr.opt.Ascending { 1127 sorted = sort.Reverse(sorted) 1128 } 1129 sort.Sort(sorted) 1130 } 1131 1132 // Assume the points are already sorted until proven otherwise. 1133 sortedByTime := true 1134 // Emit the points for each name & tag combination. 1135 a := make([]FloatPoint, 0, len(m)) 1136 for _, k := range keys { 1137 rp := m[k] 1138 points := rp.Emitter.Emit() 1139 for i := len(points) - 1; i >= 0; i-- { 1140 points[i].Name = rp.Name 1141 if !itr.keepTags { 1142 points[i].Tags = rp.Tags 1143 } 1144 // Set the points time to the interval time if the reducer didn't provide one. 1145 if points[i].Time == ZeroTime { 1146 points[i].Time = startTime 1147 } else { 1148 sortedByTime = false 1149 } 1150 a = append(a, points[i]) 1151 } 1152 } 1153 // Points may be out of order. Perform a stable sort by time if requested. 1154 if !sortedByTime && itr.opt.Ordered { 1155 var sorted sort.Interface = floatPointsByTime(a) 1156 if itr.opt.Ascending { 1157 sorted = sort.Reverse(sorted) 1158 } 1159 sort.Stable(sorted) 1160 } 1161 return a, nil 1162} 1163 1164// floatStreamFloatIterator streams inputs into the iterator and emits points gradually. 1165type floatStreamFloatIterator struct { 1166 input *bufFloatIterator 1167 create func() (FloatPointAggregator, FloatPointEmitter) 1168 dims []string 1169 opt IteratorOptions 1170 m map[string]*floatReduceFloatPoint 1171 points []FloatPoint 1172} 1173 1174// newFloatStreamFloatIterator returns a new instance of floatStreamFloatIterator. 1175func newFloatStreamFloatIterator(input FloatIterator, createFn func() (FloatPointAggregator, FloatPointEmitter), opt IteratorOptions) *floatStreamFloatIterator { 1176 return &floatStreamFloatIterator{ 1177 input: newBufFloatIterator(input), 1178 create: createFn, 1179 dims: opt.GetDimensions(), 1180 opt: opt, 1181 m: make(map[string]*floatReduceFloatPoint), 1182 } 1183} 1184 1185// Stats returns stats from the input iterator. 1186func (itr *floatStreamFloatIterator) Stats() IteratorStats { return itr.input.Stats() } 1187 1188// Close closes the iterator and all child iterators. 1189func (itr *floatStreamFloatIterator) Close() error { return itr.input.Close() } 1190 1191// Next returns the next value for the stream iterator. 1192func (itr *floatStreamFloatIterator) Next() (*FloatPoint, error) { 1193 // Calculate next window if we have no more points. 1194 if len(itr.points) == 0 { 1195 var err error 1196 itr.points, err = itr.reduce() 1197 if len(itr.points) == 0 { 1198 return nil, err 1199 } 1200 } 1201 1202 // Pop next point off the stack. 1203 p := &itr.points[len(itr.points)-1] 1204 itr.points = itr.points[:len(itr.points)-1] 1205 return p, nil 1206} 1207 1208// reduce creates and manages aggregators for every point from the input. 1209// After aggregating a point, it always tries to emit a value using the emitter. 1210func (itr *floatStreamFloatIterator) reduce() ([]FloatPoint, error) { 1211 // We have already read all of the input points. 1212 if itr.m == nil { 1213 return nil, nil 1214 } 1215 1216 for { 1217 // Read next point. 1218 curr, err := itr.input.Next() 1219 if err != nil { 1220 return nil, err 1221 } else if curr == nil { 1222 // Close all of the aggregators to flush any remaining points to emit. 1223 var points []FloatPoint 1224 for _, rp := range itr.m { 1225 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 1226 if err := aggregator.Close(); err != nil { 1227 return nil, err 1228 } 1229 1230 pts := rp.Emitter.Emit() 1231 if len(pts) == 0 { 1232 continue 1233 } 1234 1235 for i := range pts { 1236 pts[i].Name = rp.Name 1237 pts[i].Tags = rp.Tags 1238 } 1239 points = append(points, pts...) 1240 } 1241 } 1242 1243 // Eliminate the aggregators and emitters. 1244 itr.m = nil 1245 return points, nil 1246 } else if curr.Nil { 1247 continue 1248 } 1249 tags := curr.Tags.Subset(itr.dims) 1250 1251 id := curr.Name 1252 if len(tags.m) > 0 { 1253 id += "\x00" + tags.ID() 1254 } 1255 1256 // Retrieve the aggregator for this name/tag combination or create one. 1257 rp := itr.m[id] 1258 if rp == nil { 1259 aggregator, emitter := itr.create() 1260 rp = &floatReduceFloatPoint{ 1261 Name: curr.Name, 1262 Tags: tags, 1263 Aggregator: aggregator, 1264 Emitter: emitter, 1265 } 1266 itr.m[id] = rp 1267 } 1268 rp.Aggregator.AggregateFloat(curr) 1269 1270 // Attempt to emit points from the aggregator. 1271 points := rp.Emitter.Emit() 1272 if len(points) == 0 { 1273 continue 1274 } 1275 1276 for i := range points { 1277 points[i].Name = rp.Name 1278 points[i].Tags = rp.Tags 1279 } 1280 return points, nil 1281 } 1282} 1283 1284// floatReduceIntegerIterator executes a reducer for every interval and buffers the result. 1285type floatReduceIntegerIterator struct { 1286 input *bufFloatIterator 1287 create func() (FloatPointAggregator, IntegerPointEmitter) 1288 dims []string 1289 opt IteratorOptions 1290 points []IntegerPoint 1291 keepTags bool 1292} 1293 1294func newFloatReduceIntegerIterator(input FloatIterator, opt IteratorOptions, createFn func() (FloatPointAggregator, IntegerPointEmitter)) *floatReduceIntegerIterator { 1295 return &floatReduceIntegerIterator{ 1296 input: newBufFloatIterator(input), 1297 create: createFn, 1298 dims: opt.GetDimensions(), 1299 opt: opt, 1300 } 1301} 1302 1303// Stats returns stats from the input iterator. 1304func (itr *floatReduceIntegerIterator) Stats() IteratorStats { return itr.input.Stats() } 1305 1306// Close closes the iterator and all child iterators. 1307func (itr *floatReduceIntegerIterator) Close() error { return itr.input.Close() } 1308 1309// Next returns the minimum value for the next available interval. 1310func (itr *floatReduceIntegerIterator) Next() (*IntegerPoint, error) { 1311 // Calculate next window if we have no more points. 1312 if len(itr.points) == 0 { 1313 var err error 1314 itr.points, err = itr.reduce() 1315 if len(itr.points) == 0 { 1316 return nil, err 1317 } 1318 } 1319 1320 // Pop next point off the stack. 1321 p := &itr.points[len(itr.points)-1] 1322 itr.points = itr.points[:len(itr.points)-1] 1323 return p, nil 1324} 1325 1326// floatReduceIntegerPoint stores the reduced data for a name/tag combination. 1327type floatReduceIntegerPoint struct { 1328 Name string 1329 Tags Tags 1330 Aggregator FloatPointAggregator 1331 Emitter IntegerPointEmitter 1332} 1333 1334// reduce executes fn once for every point in the next window. 1335// The previous value for the dimension is passed to fn. 1336func (itr *floatReduceIntegerIterator) reduce() ([]IntegerPoint, error) { 1337 // Calculate next window. 1338 var ( 1339 startTime, endTime int64 1340 window struct { 1341 name string 1342 tags string 1343 } 1344 ) 1345 for { 1346 p, err := itr.input.Next() 1347 if err != nil || p == nil { 1348 return nil, err 1349 } else if p.Nil { 1350 continue 1351 } 1352 1353 // Unread the point so it can be processed. 1354 itr.input.unread(p) 1355 startTime, endTime = itr.opt.Window(p.Time) 1356 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 1357 break 1358 } 1359 1360 // Create points by tags. 1361 m := make(map[string]*floatReduceIntegerPoint) 1362 for { 1363 // Read next point. 1364 curr, err := itr.input.NextInWindow(startTime, endTime) 1365 if err != nil { 1366 return nil, err 1367 } else if curr == nil { 1368 break 1369 } else if curr.Nil { 1370 continue 1371 } else if curr.Name != window.name { 1372 itr.input.unread(curr) 1373 break 1374 } 1375 1376 // Ensure this point is within the same final window. 1377 if curr.Name != window.name { 1378 itr.input.unread(curr) 1379 break 1380 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 1381 itr.input.unread(curr) 1382 break 1383 } 1384 1385 // Retrieve the tags on this point for this level of the query. 1386 // This may be different than the bucket dimensions. 1387 tags := curr.Tags.Subset(itr.dims) 1388 id := tags.ID() 1389 1390 // Retrieve the aggregator for this name/tag combination or create one. 1391 rp := m[id] 1392 if rp == nil { 1393 aggregator, emitter := itr.create() 1394 rp = &floatReduceIntegerPoint{ 1395 Name: curr.Name, 1396 Tags: tags, 1397 Aggregator: aggregator, 1398 Emitter: emitter, 1399 } 1400 m[id] = rp 1401 } 1402 rp.Aggregator.AggregateFloat(curr) 1403 } 1404 1405 keys := make([]string, 0, len(m)) 1406 for k := range m { 1407 keys = append(keys, k) 1408 } 1409 1410 // Reverse sort points by name & tag. 1411 // This ensures a consistent order of output. 1412 if len(keys) > 0 { 1413 var sorted sort.Interface = sort.StringSlice(keys) 1414 if itr.opt.Ascending { 1415 sorted = sort.Reverse(sorted) 1416 } 1417 sort.Sort(sorted) 1418 } 1419 1420 // Assume the points are already sorted until proven otherwise. 1421 sortedByTime := true 1422 // Emit the points for each name & tag combination. 1423 a := make([]IntegerPoint, 0, len(m)) 1424 for _, k := range keys { 1425 rp := m[k] 1426 points := rp.Emitter.Emit() 1427 for i := len(points) - 1; i >= 0; i-- { 1428 points[i].Name = rp.Name 1429 if !itr.keepTags { 1430 points[i].Tags = rp.Tags 1431 } 1432 // Set the points time to the interval time if the reducer didn't provide one. 1433 if points[i].Time == ZeroTime { 1434 points[i].Time = startTime 1435 } else { 1436 sortedByTime = false 1437 } 1438 a = append(a, points[i]) 1439 } 1440 } 1441 // Points may be out of order. Perform a stable sort by time if requested. 1442 if !sortedByTime && itr.opt.Ordered { 1443 var sorted sort.Interface = integerPointsByTime(a) 1444 if itr.opt.Ascending { 1445 sorted = sort.Reverse(sorted) 1446 } 1447 sort.Stable(sorted) 1448 } 1449 return a, nil 1450} 1451 1452// floatStreamIntegerIterator streams inputs into the iterator and emits points gradually. 1453type floatStreamIntegerIterator struct { 1454 input *bufFloatIterator 1455 create func() (FloatPointAggregator, IntegerPointEmitter) 1456 dims []string 1457 opt IteratorOptions 1458 m map[string]*floatReduceIntegerPoint 1459 points []IntegerPoint 1460} 1461 1462// newFloatStreamIntegerIterator returns a new instance of floatStreamIntegerIterator. 1463func newFloatStreamIntegerIterator(input FloatIterator, createFn func() (FloatPointAggregator, IntegerPointEmitter), opt IteratorOptions) *floatStreamIntegerIterator { 1464 return &floatStreamIntegerIterator{ 1465 input: newBufFloatIterator(input), 1466 create: createFn, 1467 dims: opt.GetDimensions(), 1468 opt: opt, 1469 m: make(map[string]*floatReduceIntegerPoint), 1470 } 1471} 1472 1473// Stats returns stats from the input iterator. 1474func (itr *floatStreamIntegerIterator) Stats() IteratorStats { return itr.input.Stats() } 1475 1476// Close closes the iterator and all child iterators. 1477func (itr *floatStreamIntegerIterator) Close() error { return itr.input.Close() } 1478 1479// Next returns the next value for the stream iterator. 1480func (itr *floatStreamIntegerIterator) Next() (*IntegerPoint, error) { 1481 // Calculate next window if we have no more points. 1482 if len(itr.points) == 0 { 1483 var err error 1484 itr.points, err = itr.reduce() 1485 if len(itr.points) == 0 { 1486 return nil, err 1487 } 1488 } 1489 1490 // Pop next point off the stack. 1491 p := &itr.points[len(itr.points)-1] 1492 itr.points = itr.points[:len(itr.points)-1] 1493 return p, nil 1494} 1495 1496// reduce creates and manages aggregators for every point from the input. 1497// After aggregating a point, it always tries to emit a value using the emitter. 1498func (itr *floatStreamIntegerIterator) reduce() ([]IntegerPoint, error) { 1499 // We have already read all of the input points. 1500 if itr.m == nil { 1501 return nil, nil 1502 } 1503 1504 for { 1505 // Read next point. 1506 curr, err := itr.input.Next() 1507 if err != nil { 1508 return nil, err 1509 } else if curr == nil { 1510 // Close all of the aggregators to flush any remaining points to emit. 1511 var points []IntegerPoint 1512 for _, rp := range itr.m { 1513 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 1514 if err := aggregator.Close(); err != nil { 1515 return nil, err 1516 } 1517 1518 pts := rp.Emitter.Emit() 1519 if len(pts) == 0 { 1520 continue 1521 } 1522 1523 for i := range pts { 1524 pts[i].Name = rp.Name 1525 pts[i].Tags = rp.Tags 1526 } 1527 points = append(points, pts...) 1528 } 1529 } 1530 1531 // Eliminate the aggregators and emitters. 1532 itr.m = nil 1533 return points, nil 1534 } else if curr.Nil { 1535 continue 1536 } 1537 tags := curr.Tags.Subset(itr.dims) 1538 1539 id := curr.Name 1540 if len(tags.m) > 0 { 1541 id += "\x00" + tags.ID() 1542 } 1543 1544 // Retrieve the aggregator for this name/tag combination or create one. 1545 rp := itr.m[id] 1546 if rp == nil { 1547 aggregator, emitter := itr.create() 1548 rp = &floatReduceIntegerPoint{ 1549 Name: curr.Name, 1550 Tags: tags, 1551 Aggregator: aggregator, 1552 Emitter: emitter, 1553 } 1554 itr.m[id] = rp 1555 } 1556 rp.Aggregator.AggregateFloat(curr) 1557 1558 // Attempt to emit points from the aggregator. 1559 points := rp.Emitter.Emit() 1560 if len(points) == 0 { 1561 continue 1562 } 1563 1564 for i := range points { 1565 points[i].Name = rp.Name 1566 points[i].Tags = rp.Tags 1567 } 1568 return points, nil 1569 } 1570} 1571 1572// floatReduceUnsignedIterator executes a reducer for every interval and buffers the result. 1573type floatReduceUnsignedIterator struct { 1574 input *bufFloatIterator 1575 create func() (FloatPointAggregator, UnsignedPointEmitter) 1576 dims []string 1577 opt IteratorOptions 1578 points []UnsignedPoint 1579 keepTags bool 1580} 1581 1582func newFloatReduceUnsignedIterator(input FloatIterator, opt IteratorOptions, createFn func() (FloatPointAggregator, UnsignedPointEmitter)) *floatReduceUnsignedIterator { 1583 return &floatReduceUnsignedIterator{ 1584 input: newBufFloatIterator(input), 1585 create: createFn, 1586 dims: opt.GetDimensions(), 1587 opt: opt, 1588 } 1589} 1590 1591// Stats returns stats from the input iterator. 1592func (itr *floatReduceUnsignedIterator) Stats() IteratorStats { return itr.input.Stats() } 1593 1594// Close closes the iterator and all child iterators. 1595func (itr *floatReduceUnsignedIterator) Close() error { return itr.input.Close() } 1596 1597// Next returns the minimum value for the next available interval. 1598func (itr *floatReduceUnsignedIterator) Next() (*UnsignedPoint, error) { 1599 // Calculate next window if we have no more points. 1600 if len(itr.points) == 0 { 1601 var err error 1602 itr.points, err = itr.reduce() 1603 if len(itr.points) == 0 { 1604 return nil, err 1605 } 1606 } 1607 1608 // Pop next point off the stack. 1609 p := &itr.points[len(itr.points)-1] 1610 itr.points = itr.points[:len(itr.points)-1] 1611 return p, nil 1612} 1613 1614// floatReduceUnsignedPoint stores the reduced data for a name/tag combination. 1615type floatReduceUnsignedPoint struct { 1616 Name string 1617 Tags Tags 1618 Aggregator FloatPointAggregator 1619 Emitter UnsignedPointEmitter 1620} 1621 1622// reduce executes fn once for every point in the next window. 1623// The previous value for the dimension is passed to fn. 1624func (itr *floatReduceUnsignedIterator) reduce() ([]UnsignedPoint, error) { 1625 // Calculate next window. 1626 var ( 1627 startTime, endTime int64 1628 window struct { 1629 name string 1630 tags string 1631 } 1632 ) 1633 for { 1634 p, err := itr.input.Next() 1635 if err != nil || p == nil { 1636 return nil, err 1637 } else if p.Nil { 1638 continue 1639 } 1640 1641 // Unread the point so it can be processed. 1642 itr.input.unread(p) 1643 startTime, endTime = itr.opt.Window(p.Time) 1644 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 1645 break 1646 } 1647 1648 // Create points by tags. 1649 m := make(map[string]*floatReduceUnsignedPoint) 1650 for { 1651 // Read next point. 1652 curr, err := itr.input.NextInWindow(startTime, endTime) 1653 if err != nil { 1654 return nil, err 1655 } else if curr == nil { 1656 break 1657 } else if curr.Nil { 1658 continue 1659 } else if curr.Name != window.name { 1660 itr.input.unread(curr) 1661 break 1662 } 1663 1664 // Ensure this point is within the same final window. 1665 if curr.Name != window.name { 1666 itr.input.unread(curr) 1667 break 1668 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 1669 itr.input.unread(curr) 1670 break 1671 } 1672 1673 // Retrieve the tags on this point for this level of the query. 1674 // This may be different than the bucket dimensions. 1675 tags := curr.Tags.Subset(itr.dims) 1676 id := tags.ID() 1677 1678 // Retrieve the aggregator for this name/tag combination or create one. 1679 rp := m[id] 1680 if rp == nil { 1681 aggregator, emitter := itr.create() 1682 rp = &floatReduceUnsignedPoint{ 1683 Name: curr.Name, 1684 Tags: tags, 1685 Aggregator: aggregator, 1686 Emitter: emitter, 1687 } 1688 m[id] = rp 1689 } 1690 rp.Aggregator.AggregateFloat(curr) 1691 } 1692 1693 keys := make([]string, 0, len(m)) 1694 for k := range m { 1695 keys = append(keys, k) 1696 } 1697 1698 // Reverse sort points by name & tag. 1699 // This ensures a consistent order of output. 1700 if len(keys) > 0 { 1701 var sorted sort.Interface = sort.StringSlice(keys) 1702 if itr.opt.Ascending { 1703 sorted = sort.Reverse(sorted) 1704 } 1705 sort.Sort(sorted) 1706 } 1707 1708 // Assume the points are already sorted until proven otherwise. 1709 sortedByTime := true 1710 // Emit the points for each name & tag combination. 1711 a := make([]UnsignedPoint, 0, len(m)) 1712 for _, k := range keys { 1713 rp := m[k] 1714 points := rp.Emitter.Emit() 1715 for i := len(points) - 1; i >= 0; i-- { 1716 points[i].Name = rp.Name 1717 if !itr.keepTags { 1718 points[i].Tags = rp.Tags 1719 } 1720 // Set the points time to the interval time if the reducer didn't provide one. 1721 if points[i].Time == ZeroTime { 1722 points[i].Time = startTime 1723 } else { 1724 sortedByTime = false 1725 } 1726 a = append(a, points[i]) 1727 } 1728 } 1729 // Points may be out of order. Perform a stable sort by time if requested. 1730 if !sortedByTime && itr.opt.Ordered { 1731 var sorted sort.Interface = unsignedPointsByTime(a) 1732 if itr.opt.Ascending { 1733 sorted = sort.Reverse(sorted) 1734 } 1735 sort.Stable(sorted) 1736 } 1737 return a, nil 1738} 1739 1740// floatStreamUnsignedIterator streams inputs into the iterator and emits points gradually. 1741type floatStreamUnsignedIterator struct { 1742 input *bufFloatIterator 1743 create func() (FloatPointAggregator, UnsignedPointEmitter) 1744 dims []string 1745 opt IteratorOptions 1746 m map[string]*floatReduceUnsignedPoint 1747 points []UnsignedPoint 1748} 1749 1750// newFloatStreamUnsignedIterator returns a new instance of floatStreamUnsignedIterator. 1751func newFloatStreamUnsignedIterator(input FloatIterator, createFn func() (FloatPointAggregator, UnsignedPointEmitter), opt IteratorOptions) *floatStreamUnsignedIterator { 1752 return &floatStreamUnsignedIterator{ 1753 input: newBufFloatIterator(input), 1754 create: createFn, 1755 dims: opt.GetDimensions(), 1756 opt: opt, 1757 m: make(map[string]*floatReduceUnsignedPoint), 1758 } 1759} 1760 1761// Stats returns stats from the input iterator. 1762func (itr *floatStreamUnsignedIterator) Stats() IteratorStats { return itr.input.Stats() } 1763 1764// Close closes the iterator and all child iterators. 1765func (itr *floatStreamUnsignedIterator) Close() error { return itr.input.Close() } 1766 1767// Next returns the next value for the stream iterator. 1768func (itr *floatStreamUnsignedIterator) Next() (*UnsignedPoint, error) { 1769 // Calculate next window if we have no more points. 1770 if len(itr.points) == 0 { 1771 var err error 1772 itr.points, err = itr.reduce() 1773 if len(itr.points) == 0 { 1774 return nil, err 1775 } 1776 } 1777 1778 // Pop next point off the stack. 1779 p := &itr.points[len(itr.points)-1] 1780 itr.points = itr.points[:len(itr.points)-1] 1781 return p, nil 1782} 1783 1784// reduce creates and manages aggregators for every point from the input. 1785// After aggregating a point, it always tries to emit a value using the emitter. 1786func (itr *floatStreamUnsignedIterator) reduce() ([]UnsignedPoint, error) { 1787 // We have already read all of the input points. 1788 if itr.m == nil { 1789 return nil, nil 1790 } 1791 1792 for { 1793 // Read next point. 1794 curr, err := itr.input.Next() 1795 if err != nil { 1796 return nil, err 1797 } else if curr == nil { 1798 // Close all of the aggregators to flush any remaining points to emit. 1799 var points []UnsignedPoint 1800 for _, rp := range itr.m { 1801 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 1802 if err := aggregator.Close(); err != nil { 1803 return nil, err 1804 } 1805 1806 pts := rp.Emitter.Emit() 1807 if len(pts) == 0 { 1808 continue 1809 } 1810 1811 for i := range pts { 1812 pts[i].Name = rp.Name 1813 pts[i].Tags = rp.Tags 1814 } 1815 points = append(points, pts...) 1816 } 1817 } 1818 1819 // Eliminate the aggregators and emitters. 1820 itr.m = nil 1821 return points, nil 1822 } else if curr.Nil { 1823 continue 1824 } 1825 tags := curr.Tags.Subset(itr.dims) 1826 1827 id := curr.Name 1828 if len(tags.m) > 0 { 1829 id += "\x00" + tags.ID() 1830 } 1831 1832 // Retrieve the aggregator for this name/tag combination or create one. 1833 rp := itr.m[id] 1834 if rp == nil { 1835 aggregator, emitter := itr.create() 1836 rp = &floatReduceUnsignedPoint{ 1837 Name: curr.Name, 1838 Tags: tags, 1839 Aggregator: aggregator, 1840 Emitter: emitter, 1841 } 1842 itr.m[id] = rp 1843 } 1844 rp.Aggregator.AggregateFloat(curr) 1845 1846 // Attempt to emit points from the aggregator. 1847 points := rp.Emitter.Emit() 1848 if len(points) == 0 { 1849 continue 1850 } 1851 1852 for i := range points { 1853 points[i].Name = rp.Name 1854 points[i].Tags = rp.Tags 1855 } 1856 return points, nil 1857 } 1858} 1859 1860// floatReduceStringIterator executes a reducer for every interval and buffers the result. 1861type floatReduceStringIterator struct { 1862 input *bufFloatIterator 1863 create func() (FloatPointAggregator, StringPointEmitter) 1864 dims []string 1865 opt IteratorOptions 1866 points []StringPoint 1867 keepTags bool 1868} 1869 1870func newFloatReduceStringIterator(input FloatIterator, opt IteratorOptions, createFn func() (FloatPointAggregator, StringPointEmitter)) *floatReduceStringIterator { 1871 return &floatReduceStringIterator{ 1872 input: newBufFloatIterator(input), 1873 create: createFn, 1874 dims: opt.GetDimensions(), 1875 opt: opt, 1876 } 1877} 1878 1879// Stats returns stats from the input iterator. 1880func (itr *floatReduceStringIterator) Stats() IteratorStats { return itr.input.Stats() } 1881 1882// Close closes the iterator and all child iterators. 1883func (itr *floatReduceStringIterator) Close() error { return itr.input.Close() } 1884 1885// Next returns the minimum value for the next available interval. 1886func (itr *floatReduceStringIterator) Next() (*StringPoint, error) { 1887 // Calculate next window if we have no more points. 1888 if len(itr.points) == 0 { 1889 var err error 1890 itr.points, err = itr.reduce() 1891 if len(itr.points) == 0 { 1892 return nil, err 1893 } 1894 } 1895 1896 // Pop next point off the stack. 1897 p := &itr.points[len(itr.points)-1] 1898 itr.points = itr.points[:len(itr.points)-1] 1899 return p, nil 1900} 1901 1902// floatReduceStringPoint stores the reduced data for a name/tag combination. 1903type floatReduceStringPoint struct { 1904 Name string 1905 Tags Tags 1906 Aggregator FloatPointAggregator 1907 Emitter StringPointEmitter 1908} 1909 1910// reduce executes fn once for every point in the next window. 1911// The previous value for the dimension is passed to fn. 1912func (itr *floatReduceStringIterator) reduce() ([]StringPoint, error) { 1913 // Calculate next window. 1914 var ( 1915 startTime, endTime int64 1916 window struct { 1917 name string 1918 tags string 1919 } 1920 ) 1921 for { 1922 p, err := itr.input.Next() 1923 if err != nil || p == nil { 1924 return nil, err 1925 } else if p.Nil { 1926 continue 1927 } 1928 1929 // Unread the point so it can be processed. 1930 itr.input.unread(p) 1931 startTime, endTime = itr.opt.Window(p.Time) 1932 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 1933 break 1934 } 1935 1936 // Create points by tags. 1937 m := make(map[string]*floatReduceStringPoint) 1938 for { 1939 // Read next point. 1940 curr, err := itr.input.NextInWindow(startTime, endTime) 1941 if err != nil { 1942 return nil, err 1943 } else if curr == nil { 1944 break 1945 } else if curr.Nil { 1946 continue 1947 } else if curr.Name != window.name { 1948 itr.input.unread(curr) 1949 break 1950 } 1951 1952 // Ensure this point is within the same final window. 1953 if curr.Name != window.name { 1954 itr.input.unread(curr) 1955 break 1956 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 1957 itr.input.unread(curr) 1958 break 1959 } 1960 1961 // Retrieve the tags on this point for this level of the query. 1962 // This may be different than the bucket dimensions. 1963 tags := curr.Tags.Subset(itr.dims) 1964 id := tags.ID() 1965 1966 // Retrieve the aggregator for this name/tag combination or create one. 1967 rp := m[id] 1968 if rp == nil { 1969 aggregator, emitter := itr.create() 1970 rp = &floatReduceStringPoint{ 1971 Name: curr.Name, 1972 Tags: tags, 1973 Aggregator: aggregator, 1974 Emitter: emitter, 1975 } 1976 m[id] = rp 1977 } 1978 rp.Aggregator.AggregateFloat(curr) 1979 } 1980 1981 keys := make([]string, 0, len(m)) 1982 for k := range m { 1983 keys = append(keys, k) 1984 } 1985 1986 // Reverse sort points by name & tag. 1987 // This ensures a consistent order of output. 1988 if len(keys) > 0 { 1989 var sorted sort.Interface = sort.StringSlice(keys) 1990 if itr.opt.Ascending { 1991 sorted = sort.Reverse(sorted) 1992 } 1993 sort.Sort(sorted) 1994 } 1995 1996 // Assume the points are already sorted until proven otherwise. 1997 sortedByTime := true 1998 // Emit the points for each name & tag combination. 1999 a := make([]StringPoint, 0, len(m)) 2000 for _, k := range keys { 2001 rp := m[k] 2002 points := rp.Emitter.Emit() 2003 for i := len(points) - 1; i >= 0; i-- { 2004 points[i].Name = rp.Name 2005 if !itr.keepTags { 2006 points[i].Tags = rp.Tags 2007 } 2008 // Set the points time to the interval time if the reducer didn't provide one. 2009 if points[i].Time == ZeroTime { 2010 points[i].Time = startTime 2011 } else { 2012 sortedByTime = false 2013 } 2014 a = append(a, points[i]) 2015 } 2016 } 2017 // Points may be out of order. Perform a stable sort by time if requested. 2018 if !sortedByTime && itr.opt.Ordered { 2019 var sorted sort.Interface = stringPointsByTime(a) 2020 if itr.opt.Ascending { 2021 sorted = sort.Reverse(sorted) 2022 } 2023 sort.Stable(sorted) 2024 } 2025 return a, nil 2026} 2027 2028// floatStreamStringIterator streams inputs into the iterator and emits points gradually. 2029type floatStreamStringIterator struct { 2030 input *bufFloatIterator 2031 create func() (FloatPointAggregator, StringPointEmitter) 2032 dims []string 2033 opt IteratorOptions 2034 m map[string]*floatReduceStringPoint 2035 points []StringPoint 2036} 2037 2038// newFloatStreamStringIterator returns a new instance of floatStreamStringIterator. 2039func newFloatStreamStringIterator(input FloatIterator, createFn func() (FloatPointAggregator, StringPointEmitter), opt IteratorOptions) *floatStreamStringIterator { 2040 return &floatStreamStringIterator{ 2041 input: newBufFloatIterator(input), 2042 create: createFn, 2043 dims: opt.GetDimensions(), 2044 opt: opt, 2045 m: make(map[string]*floatReduceStringPoint), 2046 } 2047} 2048 2049// Stats returns stats from the input iterator. 2050func (itr *floatStreamStringIterator) Stats() IteratorStats { return itr.input.Stats() } 2051 2052// Close closes the iterator and all child iterators. 2053func (itr *floatStreamStringIterator) Close() error { return itr.input.Close() } 2054 2055// Next returns the next value for the stream iterator. 2056func (itr *floatStreamStringIterator) Next() (*StringPoint, error) { 2057 // Calculate next window if we have no more points. 2058 if len(itr.points) == 0 { 2059 var err error 2060 itr.points, err = itr.reduce() 2061 if len(itr.points) == 0 { 2062 return nil, err 2063 } 2064 } 2065 2066 // Pop next point off the stack. 2067 p := &itr.points[len(itr.points)-1] 2068 itr.points = itr.points[:len(itr.points)-1] 2069 return p, nil 2070} 2071 2072// reduce creates and manages aggregators for every point from the input. 2073// After aggregating a point, it always tries to emit a value using the emitter. 2074func (itr *floatStreamStringIterator) reduce() ([]StringPoint, error) { 2075 // We have already read all of the input points. 2076 if itr.m == nil { 2077 return nil, nil 2078 } 2079 2080 for { 2081 // Read next point. 2082 curr, err := itr.input.Next() 2083 if err != nil { 2084 return nil, err 2085 } else if curr == nil { 2086 // Close all of the aggregators to flush any remaining points to emit. 2087 var points []StringPoint 2088 for _, rp := range itr.m { 2089 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 2090 if err := aggregator.Close(); err != nil { 2091 return nil, err 2092 } 2093 2094 pts := rp.Emitter.Emit() 2095 if len(pts) == 0 { 2096 continue 2097 } 2098 2099 for i := range pts { 2100 pts[i].Name = rp.Name 2101 pts[i].Tags = rp.Tags 2102 } 2103 points = append(points, pts...) 2104 } 2105 } 2106 2107 // Eliminate the aggregators and emitters. 2108 itr.m = nil 2109 return points, nil 2110 } else if curr.Nil { 2111 continue 2112 } 2113 tags := curr.Tags.Subset(itr.dims) 2114 2115 id := curr.Name 2116 if len(tags.m) > 0 { 2117 id += "\x00" + tags.ID() 2118 } 2119 2120 // Retrieve the aggregator for this name/tag combination or create one. 2121 rp := itr.m[id] 2122 if rp == nil { 2123 aggregator, emitter := itr.create() 2124 rp = &floatReduceStringPoint{ 2125 Name: curr.Name, 2126 Tags: tags, 2127 Aggregator: aggregator, 2128 Emitter: emitter, 2129 } 2130 itr.m[id] = rp 2131 } 2132 rp.Aggregator.AggregateFloat(curr) 2133 2134 // Attempt to emit points from the aggregator. 2135 points := rp.Emitter.Emit() 2136 if len(points) == 0 { 2137 continue 2138 } 2139 2140 for i := range points { 2141 points[i].Name = rp.Name 2142 points[i].Tags = rp.Tags 2143 } 2144 return points, nil 2145 } 2146} 2147 2148// floatReduceBooleanIterator executes a reducer for every interval and buffers the result. 2149type floatReduceBooleanIterator struct { 2150 input *bufFloatIterator 2151 create func() (FloatPointAggregator, BooleanPointEmitter) 2152 dims []string 2153 opt IteratorOptions 2154 points []BooleanPoint 2155 keepTags bool 2156} 2157 2158func newFloatReduceBooleanIterator(input FloatIterator, opt IteratorOptions, createFn func() (FloatPointAggregator, BooleanPointEmitter)) *floatReduceBooleanIterator { 2159 return &floatReduceBooleanIterator{ 2160 input: newBufFloatIterator(input), 2161 create: createFn, 2162 dims: opt.GetDimensions(), 2163 opt: opt, 2164 } 2165} 2166 2167// Stats returns stats from the input iterator. 2168func (itr *floatReduceBooleanIterator) Stats() IteratorStats { return itr.input.Stats() } 2169 2170// Close closes the iterator and all child iterators. 2171func (itr *floatReduceBooleanIterator) Close() error { return itr.input.Close() } 2172 2173// Next returns the minimum value for the next available interval. 2174func (itr *floatReduceBooleanIterator) Next() (*BooleanPoint, error) { 2175 // Calculate next window if we have no more points. 2176 if len(itr.points) == 0 { 2177 var err error 2178 itr.points, err = itr.reduce() 2179 if len(itr.points) == 0 { 2180 return nil, err 2181 } 2182 } 2183 2184 // Pop next point off the stack. 2185 p := &itr.points[len(itr.points)-1] 2186 itr.points = itr.points[:len(itr.points)-1] 2187 return p, nil 2188} 2189 2190// floatReduceBooleanPoint stores the reduced data for a name/tag combination. 2191type floatReduceBooleanPoint struct { 2192 Name string 2193 Tags Tags 2194 Aggregator FloatPointAggregator 2195 Emitter BooleanPointEmitter 2196} 2197 2198// reduce executes fn once for every point in the next window. 2199// The previous value for the dimension is passed to fn. 2200func (itr *floatReduceBooleanIterator) reduce() ([]BooleanPoint, error) { 2201 // Calculate next window. 2202 var ( 2203 startTime, endTime int64 2204 window struct { 2205 name string 2206 tags string 2207 } 2208 ) 2209 for { 2210 p, err := itr.input.Next() 2211 if err != nil || p == nil { 2212 return nil, err 2213 } else if p.Nil { 2214 continue 2215 } 2216 2217 // Unread the point so it can be processed. 2218 itr.input.unread(p) 2219 startTime, endTime = itr.opt.Window(p.Time) 2220 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 2221 break 2222 } 2223 2224 // Create points by tags. 2225 m := make(map[string]*floatReduceBooleanPoint) 2226 for { 2227 // Read next point. 2228 curr, err := itr.input.NextInWindow(startTime, endTime) 2229 if err != nil { 2230 return nil, err 2231 } else if curr == nil { 2232 break 2233 } else if curr.Nil { 2234 continue 2235 } else if curr.Name != window.name { 2236 itr.input.unread(curr) 2237 break 2238 } 2239 2240 // Ensure this point is within the same final window. 2241 if curr.Name != window.name { 2242 itr.input.unread(curr) 2243 break 2244 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 2245 itr.input.unread(curr) 2246 break 2247 } 2248 2249 // Retrieve the tags on this point for this level of the query. 2250 // This may be different than the bucket dimensions. 2251 tags := curr.Tags.Subset(itr.dims) 2252 id := tags.ID() 2253 2254 // Retrieve the aggregator for this name/tag combination or create one. 2255 rp := m[id] 2256 if rp == nil { 2257 aggregator, emitter := itr.create() 2258 rp = &floatReduceBooleanPoint{ 2259 Name: curr.Name, 2260 Tags: tags, 2261 Aggregator: aggregator, 2262 Emitter: emitter, 2263 } 2264 m[id] = rp 2265 } 2266 rp.Aggregator.AggregateFloat(curr) 2267 } 2268 2269 keys := make([]string, 0, len(m)) 2270 for k := range m { 2271 keys = append(keys, k) 2272 } 2273 2274 // Reverse sort points by name & tag. 2275 // This ensures a consistent order of output. 2276 if len(keys) > 0 { 2277 var sorted sort.Interface = sort.StringSlice(keys) 2278 if itr.opt.Ascending { 2279 sorted = sort.Reverse(sorted) 2280 } 2281 sort.Sort(sorted) 2282 } 2283 2284 // Assume the points are already sorted until proven otherwise. 2285 sortedByTime := true 2286 // Emit the points for each name & tag combination. 2287 a := make([]BooleanPoint, 0, len(m)) 2288 for _, k := range keys { 2289 rp := m[k] 2290 points := rp.Emitter.Emit() 2291 for i := len(points) - 1; i >= 0; i-- { 2292 points[i].Name = rp.Name 2293 if !itr.keepTags { 2294 points[i].Tags = rp.Tags 2295 } 2296 // Set the points time to the interval time if the reducer didn't provide one. 2297 if points[i].Time == ZeroTime { 2298 points[i].Time = startTime 2299 } else { 2300 sortedByTime = false 2301 } 2302 a = append(a, points[i]) 2303 } 2304 } 2305 // Points may be out of order. Perform a stable sort by time if requested. 2306 if !sortedByTime && itr.opt.Ordered { 2307 var sorted sort.Interface = booleanPointsByTime(a) 2308 if itr.opt.Ascending { 2309 sorted = sort.Reverse(sorted) 2310 } 2311 sort.Stable(sorted) 2312 } 2313 return a, nil 2314} 2315 2316// floatStreamBooleanIterator streams inputs into the iterator and emits points gradually. 2317type floatStreamBooleanIterator struct { 2318 input *bufFloatIterator 2319 create func() (FloatPointAggregator, BooleanPointEmitter) 2320 dims []string 2321 opt IteratorOptions 2322 m map[string]*floatReduceBooleanPoint 2323 points []BooleanPoint 2324} 2325 2326// newFloatStreamBooleanIterator returns a new instance of floatStreamBooleanIterator. 2327func newFloatStreamBooleanIterator(input FloatIterator, createFn func() (FloatPointAggregator, BooleanPointEmitter), opt IteratorOptions) *floatStreamBooleanIterator { 2328 return &floatStreamBooleanIterator{ 2329 input: newBufFloatIterator(input), 2330 create: createFn, 2331 dims: opt.GetDimensions(), 2332 opt: opt, 2333 m: make(map[string]*floatReduceBooleanPoint), 2334 } 2335} 2336 2337// Stats returns stats from the input iterator. 2338func (itr *floatStreamBooleanIterator) Stats() IteratorStats { return itr.input.Stats() } 2339 2340// Close closes the iterator and all child iterators. 2341func (itr *floatStreamBooleanIterator) Close() error { return itr.input.Close() } 2342 2343// Next returns the next value for the stream iterator. 2344func (itr *floatStreamBooleanIterator) Next() (*BooleanPoint, error) { 2345 // Calculate next window if we have no more points. 2346 if len(itr.points) == 0 { 2347 var err error 2348 itr.points, err = itr.reduce() 2349 if len(itr.points) == 0 { 2350 return nil, err 2351 } 2352 } 2353 2354 // Pop next point off the stack. 2355 p := &itr.points[len(itr.points)-1] 2356 itr.points = itr.points[:len(itr.points)-1] 2357 return p, nil 2358} 2359 2360// reduce creates and manages aggregators for every point from the input. 2361// After aggregating a point, it always tries to emit a value using the emitter. 2362func (itr *floatStreamBooleanIterator) reduce() ([]BooleanPoint, error) { 2363 // We have already read all of the input points. 2364 if itr.m == nil { 2365 return nil, nil 2366 } 2367 2368 for { 2369 // Read next point. 2370 curr, err := itr.input.Next() 2371 if err != nil { 2372 return nil, err 2373 } else if curr == nil { 2374 // Close all of the aggregators to flush any remaining points to emit. 2375 var points []BooleanPoint 2376 for _, rp := range itr.m { 2377 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 2378 if err := aggregator.Close(); err != nil { 2379 return nil, err 2380 } 2381 2382 pts := rp.Emitter.Emit() 2383 if len(pts) == 0 { 2384 continue 2385 } 2386 2387 for i := range pts { 2388 pts[i].Name = rp.Name 2389 pts[i].Tags = rp.Tags 2390 } 2391 points = append(points, pts...) 2392 } 2393 } 2394 2395 // Eliminate the aggregators and emitters. 2396 itr.m = nil 2397 return points, nil 2398 } else if curr.Nil { 2399 continue 2400 } 2401 tags := curr.Tags.Subset(itr.dims) 2402 2403 id := curr.Name 2404 if len(tags.m) > 0 { 2405 id += "\x00" + tags.ID() 2406 } 2407 2408 // Retrieve the aggregator for this name/tag combination or create one. 2409 rp := itr.m[id] 2410 if rp == nil { 2411 aggregator, emitter := itr.create() 2412 rp = &floatReduceBooleanPoint{ 2413 Name: curr.Name, 2414 Tags: tags, 2415 Aggregator: aggregator, 2416 Emitter: emitter, 2417 } 2418 itr.m[id] = rp 2419 } 2420 rp.Aggregator.AggregateFloat(curr) 2421 2422 // Attempt to emit points from the aggregator. 2423 points := rp.Emitter.Emit() 2424 if len(points) == 0 { 2425 continue 2426 } 2427 2428 for i := range points { 2429 points[i].Name = rp.Name 2430 points[i].Tags = rp.Tags 2431 } 2432 return points, nil 2433 } 2434} 2435 2436// floatDedupeIterator only outputs unique points. 2437// This differs from the DistinctIterator in that it compares all aux fields too. 2438// This iterator is relatively inefficient and should only be used on small 2439// datasets such as meta query results. 2440type floatDedupeIterator struct { 2441 input FloatIterator 2442 m map[string]struct{} // lookup of points already sent 2443} 2444 2445type floatIteratorMapper struct { 2446 cur Cursor 2447 row Row 2448 driver IteratorMap // which iterator to use for the primary value, can be nil 2449 fields []IteratorMap // which iterator to use for an aux field 2450 point FloatPoint 2451} 2452 2453func newFloatIteratorMapper(cur Cursor, driver IteratorMap, fields []IteratorMap, opt IteratorOptions) *floatIteratorMapper { 2454 return &floatIteratorMapper{ 2455 cur: cur, 2456 driver: driver, 2457 fields: fields, 2458 point: FloatPoint{ 2459 Aux: make([]interface{}, len(fields)), 2460 }, 2461 } 2462} 2463 2464func (itr *floatIteratorMapper) Next() (*FloatPoint, error) { 2465 if !itr.cur.Scan(&itr.row) { 2466 if err := itr.cur.Err(); err != nil { 2467 return nil, err 2468 } 2469 return nil, nil 2470 } 2471 2472 itr.point.Time = itr.row.Time 2473 itr.point.Name = itr.row.Series.Name 2474 itr.point.Tags = itr.row.Series.Tags 2475 2476 if itr.driver != nil { 2477 if v := itr.driver.Value(&itr.row); v != nil { 2478 if v, ok := castToFloat(v); ok { 2479 itr.point.Value = v 2480 itr.point.Nil = false 2481 } else { 2482 itr.point.Value = 0 2483 itr.point.Nil = true 2484 } 2485 } else { 2486 itr.point.Value = 0 2487 itr.point.Nil = true 2488 } 2489 } 2490 for i, f := range itr.fields { 2491 itr.point.Aux[i] = f.Value(&itr.row) 2492 } 2493 return &itr.point, nil 2494} 2495 2496func (itr *floatIteratorMapper) Stats() IteratorStats { 2497 return itr.cur.Stats() 2498} 2499 2500func (itr *floatIteratorMapper) Close() error { 2501 return itr.cur.Close() 2502} 2503 2504type floatFilterIterator struct { 2505 input FloatIterator 2506 cond influxql.Expr 2507 opt IteratorOptions 2508 m map[string]interface{} 2509} 2510 2511func newFloatFilterIterator(input FloatIterator, cond influxql.Expr, opt IteratorOptions) FloatIterator { 2512 // Strip out time conditions from the WHERE clause. 2513 // TODO(jsternberg): This should really be done for us when creating the IteratorOptions struct. 2514 n := influxql.RewriteFunc(influxql.CloneExpr(cond), func(n influxql.Node) influxql.Node { 2515 switch n := n.(type) { 2516 case *influxql.BinaryExpr: 2517 if n.LHS.String() == "time" { 2518 return &influxql.BooleanLiteral{Val: true} 2519 } 2520 } 2521 return n 2522 }) 2523 2524 cond, _ = n.(influxql.Expr) 2525 if cond == nil { 2526 return input 2527 } else if n, ok := cond.(*influxql.BooleanLiteral); ok && n.Val { 2528 return input 2529 } 2530 2531 return &floatFilterIterator{ 2532 input: input, 2533 cond: cond, 2534 opt: opt, 2535 m: make(map[string]interface{}), 2536 } 2537} 2538 2539func (itr *floatFilterIterator) Stats() IteratorStats { return itr.input.Stats() } 2540func (itr *floatFilterIterator) Close() error { return itr.input.Close() } 2541 2542func (itr *floatFilterIterator) Next() (*FloatPoint, error) { 2543 for { 2544 p, err := itr.input.Next() 2545 if err != nil || p == nil { 2546 return nil, err 2547 } 2548 2549 for i, ref := range itr.opt.Aux { 2550 itr.m[ref.Val] = p.Aux[i] 2551 } 2552 for k, v := range p.Tags.KeyValues() { 2553 itr.m[k] = v 2554 } 2555 2556 if !influxql.EvalBool(itr.cond, itr.m) { 2557 continue 2558 } 2559 return p, nil 2560 } 2561} 2562 2563type floatTagSubsetIterator struct { 2564 input FloatIterator 2565 point FloatPoint 2566 lastTags Tags 2567 dimensions []string 2568} 2569 2570func newFloatTagSubsetIterator(input FloatIterator, opt IteratorOptions) *floatTagSubsetIterator { 2571 return &floatTagSubsetIterator{ 2572 input: input, 2573 dimensions: opt.GetDimensions(), 2574 } 2575} 2576 2577func (itr *floatTagSubsetIterator) Next() (*FloatPoint, error) { 2578 p, err := itr.input.Next() 2579 if err != nil { 2580 return nil, err 2581 } else if p == nil { 2582 return nil, nil 2583 } 2584 2585 itr.point.Name = p.Name 2586 if !p.Tags.Equal(itr.lastTags) { 2587 itr.point.Tags = p.Tags.Subset(itr.dimensions) 2588 itr.lastTags = p.Tags 2589 } 2590 itr.point.Time = p.Time 2591 itr.point.Value = p.Value 2592 itr.point.Aux = p.Aux 2593 itr.point.Aggregated = p.Aggregated 2594 itr.point.Nil = p.Nil 2595 return &itr.point, nil 2596} 2597 2598func (itr *floatTagSubsetIterator) Stats() IteratorStats { 2599 return itr.input.Stats() 2600} 2601 2602func (itr *floatTagSubsetIterator) Close() error { 2603 return itr.input.Close() 2604} 2605 2606// newFloatDedupeIterator returns a new instance of floatDedupeIterator. 2607func newFloatDedupeIterator(input FloatIterator) *floatDedupeIterator { 2608 return &floatDedupeIterator{ 2609 input: input, 2610 m: make(map[string]struct{}), 2611 } 2612} 2613 2614// Stats returns stats from the input iterator. 2615func (itr *floatDedupeIterator) Stats() IteratorStats { return itr.input.Stats() } 2616 2617// Close closes the iterator and all child iterators. 2618func (itr *floatDedupeIterator) Close() error { return itr.input.Close() } 2619 2620// Next returns the next unique point from the input iterator. 2621func (itr *floatDedupeIterator) Next() (*FloatPoint, error) { 2622 for { 2623 // Read next point. 2624 p, err := itr.input.Next() 2625 if p == nil || err != nil { 2626 return nil, err 2627 } 2628 2629 // Serialize to bytes to store in lookup. 2630 buf, err := proto.Marshal(encodeFloatPoint(p)) 2631 if err != nil { 2632 return nil, err 2633 } 2634 2635 // If the point has already been output then move to the next point. 2636 if _, ok := itr.m[string(buf)]; ok { 2637 continue 2638 } 2639 2640 // Otherwise mark it as emitted and return point. 2641 itr.m[string(buf)] = struct{}{} 2642 return p, nil 2643 } 2644} 2645 2646// floatReaderIterator represents an iterator that streams from a reader. 2647type floatReaderIterator struct { 2648 r io.Reader 2649 dec *FloatPointDecoder 2650} 2651 2652// newFloatReaderIterator returns a new instance of floatReaderIterator. 2653func newFloatReaderIterator(ctx context.Context, r io.Reader, stats IteratorStats) *floatReaderIterator { 2654 dec := NewFloatPointDecoder(ctx, r) 2655 dec.stats = stats 2656 2657 return &floatReaderIterator{ 2658 r: r, 2659 dec: dec, 2660 } 2661} 2662 2663// Stats returns stats about points processed. 2664func (itr *floatReaderIterator) Stats() IteratorStats { return itr.dec.stats } 2665 2666// Close closes the underlying reader, if applicable. 2667func (itr *floatReaderIterator) Close() error { 2668 if r, ok := itr.r.(io.ReadCloser); ok { 2669 return r.Close() 2670 } 2671 return nil 2672} 2673 2674// Next returns the next point from the iterator. 2675func (itr *floatReaderIterator) Next() (*FloatPoint, error) { 2676 // OPTIMIZE(benbjohnson): Reuse point on iterator. 2677 2678 // Unmarshal next point. 2679 p := &FloatPoint{} 2680 if err := itr.dec.DecodeFloatPoint(p); err == io.EOF { 2681 return nil, nil 2682 } else if err != nil { 2683 return nil, err 2684 } 2685 return p, nil 2686} 2687 2688// IntegerIterator represents a stream of integer points. 2689type IntegerIterator interface { 2690 Iterator 2691 Next() (*IntegerPoint, error) 2692} 2693 2694// newIntegerIterators converts a slice of Iterator to a slice of IntegerIterator. 2695// Drop and closes any iterator in itrs that is not a IntegerIterator and cannot 2696// be cast to a IntegerIterator. 2697func newIntegerIterators(itrs []Iterator) []IntegerIterator { 2698 a := make([]IntegerIterator, 0, len(itrs)) 2699 for _, itr := range itrs { 2700 switch itr := itr.(type) { 2701 case IntegerIterator: 2702 a = append(a, itr) 2703 default: 2704 itr.Close() 2705 } 2706 } 2707 return a 2708} 2709 2710// bufIntegerIterator represents a buffered IntegerIterator. 2711type bufIntegerIterator struct { 2712 itr IntegerIterator 2713 buf *IntegerPoint 2714} 2715 2716// newBufIntegerIterator returns a buffered IntegerIterator. 2717func newBufIntegerIterator(itr IntegerIterator) *bufIntegerIterator { 2718 return &bufIntegerIterator{itr: itr} 2719} 2720 2721// Stats returns statistics from the input iterator. 2722func (itr *bufIntegerIterator) Stats() IteratorStats { return itr.itr.Stats() } 2723 2724// Close closes the underlying iterator. 2725func (itr *bufIntegerIterator) Close() error { return itr.itr.Close() } 2726 2727// peek returns the next point without removing it from the iterator. 2728func (itr *bufIntegerIterator) peek() (*IntegerPoint, error) { 2729 p, err := itr.Next() 2730 if err != nil { 2731 return nil, err 2732 } 2733 itr.unread(p) 2734 return p, nil 2735} 2736 2737// peekTime returns the time of the next point. 2738// Returns zero time if no more points available. 2739func (itr *bufIntegerIterator) peekTime() (int64, error) { 2740 p, err := itr.peek() 2741 if p == nil || err != nil { 2742 return ZeroTime, err 2743 } 2744 return p.Time, nil 2745} 2746 2747// Next returns the current buffer, if exists, or calls the underlying iterator. 2748func (itr *bufIntegerIterator) Next() (*IntegerPoint, error) { 2749 buf := itr.buf 2750 if buf != nil { 2751 itr.buf = nil 2752 return buf, nil 2753 } 2754 return itr.itr.Next() 2755} 2756 2757// NextInWindow returns the next value if it is between [startTime, endTime). 2758// If the next value is outside the range then it is moved to the buffer. 2759func (itr *bufIntegerIterator) NextInWindow(startTime, endTime int64) (*IntegerPoint, error) { 2760 v, err := itr.Next() 2761 if v == nil || err != nil { 2762 return nil, err 2763 } else if t := v.Time; t >= endTime || t < startTime { 2764 itr.unread(v) 2765 return nil, nil 2766 } 2767 return v, nil 2768} 2769 2770// unread sets v to the buffer. It is read on the next call to Next(). 2771func (itr *bufIntegerIterator) unread(v *IntegerPoint) { itr.buf = v } 2772 2773// integerMergeIterator represents an iterator that combines multiple integer iterators. 2774type integerMergeIterator struct { 2775 inputs []IntegerIterator 2776 heap *integerMergeHeap 2777 init bool 2778 2779 closed bool 2780 mu sync.RWMutex 2781 2782 // Current iterator and window. 2783 curr *integerMergeHeapItem 2784 window struct { 2785 name string 2786 tags string 2787 startTime int64 2788 endTime int64 2789 } 2790} 2791 2792// newIntegerMergeIterator returns a new instance of integerMergeIterator. 2793func newIntegerMergeIterator(inputs []IntegerIterator, opt IteratorOptions) *integerMergeIterator { 2794 itr := &integerMergeIterator{ 2795 inputs: inputs, 2796 heap: &integerMergeHeap{ 2797 items: make([]*integerMergeHeapItem, 0, len(inputs)), 2798 opt: opt, 2799 }, 2800 } 2801 2802 // Initialize heap items. 2803 for _, input := range inputs { 2804 // Wrap in buffer, ignore any inputs without anymore points. 2805 bufInput := newBufIntegerIterator(input) 2806 2807 // Append to the heap. 2808 itr.heap.items = append(itr.heap.items, &integerMergeHeapItem{itr: bufInput}) 2809 } 2810 2811 return itr 2812} 2813 2814// Stats returns an aggregation of stats from the underlying iterators. 2815func (itr *integerMergeIterator) Stats() IteratorStats { 2816 var stats IteratorStats 2817 for _, input := range itr.inputs { 2818 stats.Add(input.Stats()) 2819 } 2820 return stats 2821} 2822 2823// Close closes the underlying iterators. 2824func (itr *integerMergeIterator) Close() error { 2825 itr.mu.Lock() 2826 defer itr.mu.Unlock() 2827 2828 for _, input := range itr.inputs { 2829 input.Close() 2830 } 2831 itr.curr = nil 2832 itr.inputs = nil 2833 itr.heap.items = nil 2834 itr.closed = true 2835 return nil 2836} 2837 2838// Next returns the next point from the iterator. 2839func (itr *integerMergeIterator) Next() (*IntegerPoint, error) { 2840 itr.mu.RLock() 2841 defer itr.mu.RUnlock() 2842 if itr.closed { 2843 return nil, nil 2844 } 2845 2846 // Initialize the heap. This needs to be done lazily on the first call to this iterator 2847 // so that iterator initialization done through the Select() call returns quickly. 2848 // Queries can only be interrupted after the Select() call completes so any operations 2849 // done during iterator creation cannot be interrupted, which is why we do it here 2850 // instead so an interrupt can happen while initializing the heap. 2851 if !itr.init { 2852 items := itr.heap.items 2853 itr.heap.items = make([]*integerMergeHeapItem, 0, len(items)) 2854 for _, item := range items { 2855 if p, err := item.itr.peek(); err != nil { 2856 return nil, err 2857 } else if p == nil { 2858 continue 2859 } 2860 itr.heap.items = append(itr.heap.items, item) 2861 } 2862 heap.Init(itr.heap) 2863 itr.init = true 2864 } 2865 2866 for { 2867 // Retrieve the next iterator if we don't have one. 2868 if itr.curr == nil { 2869 if len(itr.heap.items) == 0 { 2870 return nil, nil 2871 } 2872 itr.curr = heap.Pop(itr.heap).(*integerMergeHeapItem) 2873 2874 // Read point and set current window. 2875 p, err := itr.curr.itr.Next() 2876 if err != nil { 2877 return nil, err 2878 } 2879 tags := p.Tags.Subset(itr.heap.opt.Dimensions) 2880 itr.window.name, itr.window.tags = p.Name, tags.ID() 2881 itr.window.startTime, itr.window.endTime = itr.heap.opt.Window(p.Time) 2882 return p, nil 2883 } 2884 2885 // Read the next point from the current iterator. 2886 p, err := itr.curr.itr.Next() 2887 if err != nil { 2888 return nil, err 2889 } 2890 2891 // If there are no more points then remove iterator from heap and find next. 2892 if p == nil { 2893 itr.curr = nil 2894 continue 2895 } 2896 2897 // Check if the point is inside of our current window. 2898 inWindow := true 2899 if window := itr.window; window.name != p.Name { 2900 inWindow = false 2901 } else if tags := p.Tags.Subset(itr.heap.opt.Dimensions); window.tags != tags.ID() { 2902 inWindow = false 2903 } else if opt := itr.heap.opt; opt.Ascending && p.Time >= window.endTime { 2904 inWindow = false 2905 } else if !opt.Ascending && p.Time < window.startTime { 2906 inWindow = false 2907 } 2908 2909 // If it's outside our window then push iterator back on the heap and find new iterator. 2910 if !inWindow { 2911 itr.curr.itr.unread(p) 2912 heap.Push(itr.heap, itr.curr) 2913 itr.curr = nil 2914 continue 2915 } 2916 2917 return p, nil 2918 } 2919} 2920 2921// integerMergeHeap represents a heap of integerMergeHeapItems. 2922// Items are sorted by their next window and then by name/tags. 2923type integerMergeHeap struct { 2924 opt IteratorOptions 2925 items []*integerMergeHeapItem 2926} 2927 2928func (h *integerMergeHeap) Len() int { return len(h.items) } 2929func (h *integerMergeHeap) Swap(i, j int) { h.items[i], h.items[j] = h.items[j], h.items[i] } 2930func (h *integerMergeHeap) Less(i, j int) bool { 2931 x, err := h.items[i].itr.peek() 2932 if err != nil { 2933 return true 2934 } 2935 y, err := h.items[j].itr.peek() 2936 if err != nil { 2937 return false 2938 } 2939 2940 if h.opt.Ascending { 2941 if x.Name != y.Name { 2942 return x.Name < y.Name 2943 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); xTags.ID() != yTags.ID() { 2944 return xTags.ID() < yTags.ID() 2945 } 2946 } else { 2947 if x.Name != y.Name { 2948 return x.Name > y.Name 2949 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); xTags.ID() != yTags.ID() { 2950 return xTags.ID() > yTags.ID() 2951 } 2952 } 2953 2954 xt, _ := h.opt.Window(x.Time) 2955 yt, _ := h.opt.Window(y.Time) 2956 2957 if h.opt.Ascending { 2958 return xt < yt 2959 } 2960 return xt > yt 2961} 2962 2963func (h *integerMergeHeap) Push(x interface{}) { 2964 h.items = append(h.items, x.(*integerMergeHeapItem)) 2965} 2966 2967func (h *integerMergeHeap) Pop() interface{} { 2968 old := h.items 2969 n := len(old) 2970 item := old[n-1] 2971 h.items = old[0 : n-1] 2972 return item 2973} 2974 2975type integerMergeHeapItem struct { 2976 itr *bufIntegerIterator 2977} 2978 2979// integerSortedMergeIterator is an iterator that sorts and merges multiple iterators into one. 2980type integerSortedMergeIterator struct { 2981 inputs []IntegerIterator 2982 heap *integerSortedMergeHeap 2983 init bool 2984} 2985 2986// newIntegerSortedMergeIterator returns an instance of integerSortedMergeIterator. 2987func newIntegerSortedMergeIterator(inputs []IntegerIterator, opt IteratorOptions) Iterator { 2988 itr := &integerSortedMergeIterator{ 2989 inputs: inputs, 2990 heap: &integerSortedMergeHeap{ 2991 items: make([]*integerSortedMergeHeapItem, 0, len(inputs)), 2992 opt: opt, 2993 }, 2994 } 2995 2996 // Initialize heap items. 2997 for _, input := range inputs { 2998 // Append to the heap. 2999 itr.heap.items = append(itr.heap.items, &integerSortedMergeHeapItem{itr: input}) 3000 } 3001 3002 return itr 3003} 3004 3005// Stats returns an aggregation of stats from the underlying iterators. 3006func (itr *integerSortedMergeIterator) Stats() IteratorStats { 3007 var stats IteratorStats 3008 for _, input := range itr.inputs { 3009 stats.Add(input.Stats()) 3010 } 3011 return stats 3012} 3013 3014// Close closes the underlying iterators. 3015func (itr *integerSortedMergeIterator) Close() error { 3016 for _, input := range itr.inputs { 3017 input.Close() 3018 } 3019 return nil 3020} 3021 3022// Next returns the next points from the iterator. 3023func (itr *integerSortedMergeIterator) Next() (*IntegerPoint, error) { return itr.pop() } 3024 3025// pop returns the next point from the heap. 3026// Reads the next point from item's cursor and puts it back on the heap. 3027func (itr *integerSortedMergeIterator) pop() (*IntegerPoint, error) { 3028 // Initialize the heap. See the MergeIterator to see why this has to be done lazily. 3029 if !itr.init { 3030 items := itr.heap.items 3031 itr.heap.items = make([]*integerSortedMergeHeapItem, 0, len(items)) 3032 for _, item := range items { 3033 var err error 3034 if item.point, err = item.itr.Next(); err != nil { 3035 return nil, err 3036 } else if item.point == nil { 3037 continue 3038 } 3039 itr.heap.items = append(itr.heap.items, item) 3040 } 3041 heap.Init(itr.heap) 3042 itr.init = true 3043 } 3044 3045 if len(itr.heap.items) == 0 { 3046 return nil, nil 3047 } 3048 3049 // Read the next item from the heap. 3050 item := heap.Pop(itr.heap).(*integerSortedMergeHeapItem) 3051 if item.err != nil { 3052 return nil, item.err 3053 } else if item.point == nil { 3054 return nil, nil 3055 } 3056 3057 // Copy the point for return. 3058 p := item.point.Clone() 3059 3060 // Read the next item from the cursor. Push back to heap if one exists. 3061 if item.point, item.err = item.itr.Next(); item.point != nil { 3062 heap.Push(itr.heap, item) 3063 } 3064 3065 return p, nil 3066} 3067 3068// integerSortedMergeHeap represents a heap of integerSortedMergeHeapItems. 3069// Items are sorted with the following priority: 3070// - By their measurement name; 3071// - By their tag keys/values; 3072// - By time; or 3073// - By their Aux field values. 3074// 3075type integerSortedMergeHeap struct { 3076 opt IteratorOptions 3077 items []*integerSortedMergeHeapItem 3078} 3079 3080func (h *integerSortedMergeHeap) Len() int { return len(h.items) } 3081func (h *integerSortedMergeHeap) Swap(i, j int) { h.items[i], h.items[j] = h.items[j], h.items[i] } 3082func (h *integerSortedMergeHeap) Less(i, j int) bool { 3083 x, y := h.items[i].point, h.items[j].point 3084 3085 if h.opt.Ascending { 3086 if x.Name != y.Name { 3087 return x.Name < y.Name 3088 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); !xTags.Equals(&yTags) { 3089 return xTags.ID() < yTags.ID() 3090 } 3091 3092 if x.Time != y.Time { 3093 return x.Time < y.Time 3094 } 3095 3096 if len(x.Aux) > 0 && len(x.Aux) == len(y.Aux) { 3097 for i := 0; i < len(x.Aux); i++ { 3098 v1, ok1 := x.Aux[i].(string) 3099 v2, ok2 := y.Aux[i].(string) 3100 if !ok1 || !ok2 { 3101 // Unsupported types used in Aux fields. Maybe they 3102 // need to be added here? 3103 return false 3104 } else if v1 == v2 { 3105 continue 3106 } 3107 return v1 < v2 3108 } 3109 } 3110 return false // Times and/or Aux fields are equal. 3111 } 3112 3113 if x.Name != y.Name { 3114 return x.Name > y.Name 3115 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); !xTags.Equals(&yTags) { 3116 return xTags.ID() > yTags.ID() 3117 } 3118 3119 if x.Time != y.Time { 3120 return x.Time > y.Time 3121 } 3122 3123 if len(x.Aux) > 0 && len(x.Aux) == len(y.Aux) { 3124 for i := 0; i < len(x.Aux); i++ { 3125 v1, ok1 := x.Aux[i].(string) 3126 v2, ok2 := y.Aux[i].(string) 3127 if !ok1 || !ok2 { 3128 // Unsupported types used in Aux fields. Maybe they 3129 // need to be added here? 3130 return false 3131 } else if v1 == v2 { 3132 continue 3133 } 3134 return v1 > v2 3135 } 3136 } 3137 return false // Times and/or Aux fields are equal. 3138} 3139 3140func (h *integerSortedMergeHeap) Push(x interface{}) { 3141 h.items = append(h.items, x.(*integerSortedMergeHeapItem)) 3142} 3143 3144func (h *integerSortedMergeHeap) Pop() interface{} { 3145 old := h.items 3146 n := len(old) 3147 item := old[n-1] 3148 h.items = old[0 : n-1] 3149 return item 3150} 3151 3152type integerSortedMergeHeapItem struct { 3153 point *IntegerPoint 3154 err error 3155 itr IntegerIterator 3156} 3157 3158// integerIteratorScanner scans the results of a IntegerIterator into a map. 3159type integerIteratorScanner struct { 3160 input *bufIntegerIterator 3161 err error 3162 keys []influxql.VarRef 3163 defaultValue interface{} 3164} 3165 3166// newIntegerIteratorScanner creates a new IteratorScanner. 3167func newIntegerIteratorScanner(input IntegerIterator, keys []influxql.VarRef, defaultValue interface{}) *integerIteratorScanner { 3168 return &integerIteratorScanner{ 3169 input: newBufIntegerIterator(input), 3170 keys: keys, 3171 defaultValue: defaultValue, 3172 } 3173} 3174 3175func (s *integerIteratorScanner) Peek() (int64, string, Tags) { 3176 if s.err != nil { 3177 return ZeroTime, "", Tags{} 3178 } 3179 3180 p, err := s.input.peek() 3181 if err != nil { 3182 s.err = err 3183 return ZeroTime, "", Tags{} 3184 } else if p == nil { 3185 return ZeroTime, "", Tags{} 3186 } 3187 return p.Time, p.Name, p.Tags 3188} 3189 3190func (s *integerIteratorScanner) ScanAt(ts int64, name string, tags Tags, m map[string]interface{}) { 3191 if s.err != nil { 3192 return 3193 } 3194 3195 p, err := s.input.Next() 3196 if err != nil { 3197 s.err = err 3198 return 3199 } else if p == nil { 3200 s.useDefaults(m) 3201 return 3202 } else if p.Time != ts || p.Name != name || !p.Tags.Equals(&tags) { 3203 s.useDefaults(m) 3204 s.input.unread(p) 3205 return 3206 } 3207 3208 if k := s.keys[0]; k.Val != "" { 3209 if p.Nil { 3210 if s.defaultValue != SkipDefault { 3211 m[k.Val] = castToType(s.defaultValue, k.Type) 3212 } 3213 } else { 3214 m[k.Val] = p.Value 3215 } 3216 } 3217 for i, v := range p.Aux { 3218 k := s.keys[i+1] 3219 switch v.(type) { 3220 case float64, int64, uint64, string, bool: 3221 m[k.Val] = v 3222 default: 3223 // Insert the fill value if one was specified. 3224 if s.defaultValue != SkipDefault { 3225 m[k.Val] = castToType(s.defaultValue, k.Type) 3226 } 3227 } 3228 } 3229} 3230 3231func (s *integerIteratorScanner) useDefaults(m map[string]interface{}) { 3232 if s.defaultValue == SkipDefault { 3233 return 3234 } 3235 for _, k := range s.keys { 3236 if k.Val == "" { 3237 continue 3238 } 3239 m[k.Val] = castToType(s.defaultValue, k.Type) 3240 } 3241} 3242 3243func (s *integerIteratorScanner) Stats() IteratorStats { return s.input.Stats() } 3244func (s *integerIteratorScanner) Err() error { return s.err } 3245func (s *integerIteratorScanner) Close() error { return s.input.Close() } 3246 3247// integerParallelIterator represents an iterator that pulls data in a separate goroutine. 3248type integerParallelIterator struct { 3249 input IntegerIterator 3250 ch chan integerPointError 3251 3252 once sync.Once 3253 closing chan struct{} 3254 wg sync.WaitGroup 3255} 3256 3257// newIntegerParallelIterator returns a new instance of integerParallelIterator. 3258func newIntegerParallelIterator(input IntegerIterator) *integerParallelIterator { 3259 itr := &integerParallelIterator{ 3260 input: input, 3261 ch: make(chan integerPointError, 256), 3262 closing: make(chan struct{}), 3263 } 3264 itr.wg.Add(1) 3265 go itr.monitor() 3266 return itr 3267} 3268 3269// Stats returns stats from the underlying iterator. 3270func (itr *integerParallelIterator) Stats() IteratorStats { return itr.input.Stats() } 3271 3272// Close closes the underlying iterators. 3273func (itr *integerParallelIterator) Close() error { 3274 itr.once.Do(func() { close(itr.closing) }) 3275 itr.wg.Wait() 3276 return itr.input.Close() 3277} 3278 3279// Next returns the next point from the iterator. 3280func (itr *integerParallelIterator) Next() (*IntegerPoint, error) { 3281 v, ok := <-itr.ch 3282 if !ok { 3283 return nil, io.EOF 3284 } 3285 return v.point, v.err 3286} 3287 3288// monitor runs in a separate goroutine and actively pulls the next point. 3289func (itr *integerParallelIterator) monitor() { 3290 defer close(itr.ch) 3291 defer itr.wg.Done() 3292 3293 for { 3294 // Read next point. 3295 p, err := itr.input.Next() 3296 if p != nil { 3297 p = p.Clone() 3298 } 3299 3300 select { 3301 case <-itr.closing: 3302 return 3303 case itr.ch <- integerPointError{point: p, err: err}: 3304 } 3305 } 3306} 3307 3308type integerPointError struct { 3309 point *IntegerPoint 3310 err error 3311} 3312 3313// integerLimitIterator represents an iterator that limits points per group. 3314type integerLimitIterator struct { 3315 input IntegerIterator 3316 opt IteratorOptions 3317 n int 3318 3319 prev struct { 3320 name string 3321 tags Tags 3322 } 3323} 3324 3325// newIntegerLimitIterator returns a new instance of integerLimitIterator. 3326func newIntegerLimitIterator(input IntegerIterator, opt IteratorOptions) *integerLimitIterator { 3327 return &integerLimitIterator{ 3328 input: input, 3329 opt: opt, 3330 } 3331} 3332 3333// Stats returns stats from the underlying iterator. 3334func (itr *integerLimitIterator) Stats() IteratorStats { return itr.input.Stats() } 3335 3336// Close closes the underlying iterators. 3337func (itr *integerLimitIterator) Close() error { return itr.input.Close() } 3338 3339// Next returns the next point from the iterator. 3340func (itr *integerLimitIterator) Next() (*IntegerPoint, error) { 3341 for { 3342 p, err := itr.input.Next() 3343 if p == nil || err != nil { 3344 return nil, err 3345 } 3346 3347 // Reset window and counter if a new window is encountered. 3348 if p.Name != itr.prev.name || !p.Tags.Equals(&itr.prev.tags) { 3349 itr.prev.name = p.Name 3350 itr.prev.tags = p.Tags 3351 itr.n = 0 3352 } 3353 3354 // Increment counter. 3355 itr.n++ 3356 3357 // Read next point if not beyond the offset. 3358 if itr.n <= itr.opt.Offset { 3359 continue 3360 } 3361 3362 // Read next point if we're beyond the limit. 3363 if itr.opt.Limit > 0 && (itr.n-itr.opt.Offset) > itr.opt.Limit { 3364 continue 3365 } 3366 3367 return p, nil 3368 } 3369} 3370 3371type integerFillIterator struct { 3372 input *bufIntegerIterator 3373 prev IntegerPoint 3374 startTime int64 3375 endTime int64 3376 auxFields []interface{} 3377 init bool 3378 opt IteratorOptions 3379 3380 window struct { 3381 name string 3382 tags Tags 3383 time int64 3384 offset int64 3385 } 3386} 3387 3388func newIntegerFillIterator(input IntegerIterator, expr influxql.Expr, opt IteratorOptions) *integerFillIterator { 3389 if opt.Fill == influxql.NullFill { 3390 if expr, ok := expr.(*influxql.Call); ok && expr.Name == "count" { 3391 opt.Fill = influxql.NumberFill 3392 opt.FillValue = int64(0) 3393 } 3394 } 3395 3396 var startTime, endTime int64 3397 if opt.Ascending { 3398 startTime, _ = opt.Window(opt.StartTime) 3399 endTime, _ = opt.Window(opt.EndTime) 3400 } else { 3401 startTime, _ = opt.Window(opt.EndTime) 3402 endTime, _ = opt.Window(opt.StartTime) 3403 } 3404 3405 var auxFields []interface{} 3406 if len(opt.Aux) > 0 { 3407 auxFields = make([]interface{}, len(opt.Aux)) 3408 } 3409 3410 return &integerFillIterator{ 3411 input: newBufIntegerIterator(input), 3412 prev: IntegerPoint{Nil: true}, 3413 startTime: startTime, 3414 endTime: endTime, 3415 auxFields: auxFields, 3416 opt: opt, 3417 } 3418} 3419 3420func (itr *integerFillIterator) Stats() IteratorStats { return itr.input.Stats() } 3421func (itr *integerFillIterator) Close() error { return itr.input.Close() } 3422 3423func (itr *integerFillIterator) Next() (*IntegerPoint, error) { 3424 if !itr.init { 3425 p, err := itr.input.peek() 3426 if p == nil || err != nil { 3427 return nil, err 3428 } 3429 itr.window.name, itr.window.tags = p.Name, p.Tags 3430 itr.window.time = itr.startTime 3431 if itr.startTime == influxql.MinTime { 3432 itr.window.time, _ = itr.opt.Window(p.Time) 3433 } 3434 if itr.opt.Location != nil { 3435 _, itr.window.offset = itr.opt.Zone(itr.window.time) 3436 } 3437 itr.init = true 3438 } 3439 3440 p, err := itr.input.Next() 3441 if err != nil { 3442 return nil, err 3443 } 3444 3445 // Check if the next point is outside of our window or is nil. 3446 if p == nil || p.Name != itr.window.name || p.Tags.ID() != itr.window.tags.ID() { 3447 // If we are inside of an interval, unread the point and continue below to 3448 // constructing a new point. 3449 if itr.opt.Ascending && itr.window.time <= itr.endTime { 3450 itr.input.unread(p) 3451 p = nil 3452 goto CONSTRUCT 3453 } else if !itr.opt.Ascending && itr.window.time >= itr.endTime && itr.endTime != influxql.MinTime { 3454 itr.input.unread(p) 3455 p = nil 3456 goto CONSTRUCT 3457 } 3458 3459 // We are *not* in a current interval. If there is no next point, 3460 // we are at the end of all intervals. 3461 if p == nil { 3462 return nil, nil 3463 } 3464 3465 // Set the new interval. 3466 itr.window.name, itr.window.tags = p.Name, p.Tags 3467 itr.window.time = itr.startTime 3468 if itr.window.time == influxql.MinTime { 3469 itr.window.time, _ = itr.opt.Window(p.Time) 3470 } 3471 if itr.opt.Location != nil { 3472 _, itr.window.offset = itr.opt.Zone(itr.window.time) 3473 } 3474 itr.prev = IntegerPoint{Nil: true} 3475 } 3476 3477 // Check if the point is our next expected point. 3478CONSTRUCT: 3479 if p == nil || (itr.opt.Ascending && p.Time > itr.window.time) || (!itr.opt.Ascending && p.Time < itr.window.time) { 3480 if p != nil { 3481 itr.input.unread(p) 3482 } 3483 3484 p = &IntegerPoint{ 3485 Name: itr.window.name, 3486 Tags: itr.window.tags, 3487 Time: itr.window.time, 3488 Aux: itr.auxFields, 3489 } 3490 3491 switch itr.opt.Fill { 3492 case influxql.LinearFill: 3493 if !itr.prev.Nil { 3494 next, err := itr.input.peek() 3495 if err != nil { 3496 return nil, err 3497 } else if next != nil && next.Name == itr.window.name && next.Tags.ID() == itr.window.tags.ID() { 3498 interval := int64(itr.opt.Interval.Duration) 3499 start := itr.window.time / interval 3500 p.Value = linearInteger(start, itr.prev.Time/interval, next.Time/interval, itr.prev.Value, next.Value) 3501 } else { 3502 p.Nil = true 3503 } 3504 } else { 3505 p.Nil = true 3506 } 3507 3508 case influxql.NullFill: 3509 p.Nil = true 3510 case influxql.NumberFill: 3511 p.Value, _ = castToInteger(itr.opt.FillValue) 3512 case influxql.PreviousFill: 3513 if !itr.prev.Nil { 3514 p.Value = itr.prev.Value 3515 p.Nil = itr.prev.Nil 3516 } else { 3517 p.Nil = true 3518 } 3519 } 3520 } else { 3521 itr.prev = *p 3522 } 3523 3524 // Advance the expected time. Do not advance to a new window here 3525 // as there may be lingering points with the same timestamp in the previous 3526 // window. 3527 if itr.opt.Ascending { 3528 itr.window.time += int64(itr.opt.Interval.Duration) 3529 } else { 3530 itr.window.time -= int64(itr.opt.Interval.Duration) 3531 } 3532 3533 // Check to see if we have passed over an offset change and adjust the time 3534 // to account for this new offset. 3535 if itr.opt.Location != nil { 3536 if _, offset := itr.opt.Zone(itr.window.time - 1); offset != itr.window.offset { 3537 diff := itr.window.offset - offset 3538 if abs(diff) < int64(itr.opt.Interval.Duration) { 3539 itr.window.time += diff 3540 } 3541 itr.window.offset = offset 3542 } 3543 } 3544 return p, nil 3545} 3546 3547// integerIntervalIterator represents a integer implementation of IntervalIterator. 3548type integerIntervalIterator struct { 3549 input IntegerIterator 3550 opt IteratorOptions 3551} 3552 3553func newIntegerIntervalIterator(input IntegerIterator, opt IteratorOptions) *integerIntervalIterator { 3554 return &integerIntervalIterator{input: input, opt: opt} 3555} 3556 3557func (itr *integerIntervalIterator) Stats() IteratorStats { return itr.input.Stats() } 3558func (itr *integerIntervalIterator) Close() error { return itr.input.Close() } 3559 3560func (itr *integerIntervalIterator) Next() (*IntegerPoint, error) { 3561 p, err := itr.input.Next() 3562 if p == nil || err != nil { 3563 return nil, err 3564 } 3565 p.Time, _ = itr.opt.Window(p.Time) 3566 // If we see the minimum allowable time, set the time to zero so we don't 3567 // break the default returned time for aggregate queries without times. 3568 if p.Time == influxql.MinTime { 3569 p.Time = 0 3570 } 3571 return p, nil 3572} 3573 3574// integerInterruptIterator represents a integer implementation of InterruptIterator. 3575type integerInterruptIterator struct { 3576 input IntegerIterator 3577 closing <-chan struct{} 3578 count int 3579} 3580 3581func newIntegerInterruptIterator(input IntegerIterator, closing <-chan struct{}) *integerInterruptIterator { 3582 return &integerInterruptIterator{input: input, closing: closing} 3583} 3584 3585func (itr *integerInterruptIterator) Stats() IteratorStats { return itr.input.Stats() } 3586func (itr *integerInterruptIterator) Close() error { return itr.input.Close() } 3587 3588func (itr *integerInterruptIterator) Next() (*IntegerPoint, error) { 3589 // Only check if the channel is closed every N points. This 3590 // intentionally checks on both 0 and N so that if the iterator 3591 // has been interrupted before the first point is emitted it will 3592 // not emit any points. 3593 if itr.count&0xFF == 0xFF { 3594 select { 3595 case <-itr.closing: 3596 return nil, itr.Close() 3597 default: 3598 // Reset iterator count to zero and fall through to emit the next point. 3599 itr.count = 0 3600 } 3601 } 3602 3603 // Increment the counter for every point read. 3604 itr.count++ 3605 return itr.input.Next() 3606} 3607 3608// integerCloseInterruptIterator represents a integer implementation of CloseInterruptIterator. 3609type integerCloseInterruptIterator struct { 3610 input IntegerIterator 3611 closing <-chan struct{} 3612 done chan struct{} 3613 once sync.Once 3614} 3615 3616func newIntegerCloseInterruptIterator(input IntegerIterator, closing <-chan struct{}) *integerCloseInterruptIterator { 3617 itr := &integerCloseInterruptIterator{ 3618 input: input, 3619 closing: closing, 3620 done: make(chan struct{}), 3621 } 3622 go itr.monitor() 3623 return itr 3624} 3625 3626func (itr *integerCloseInterruptIterator) monitor() { 3627 select { 3628 case <-itr.closing: 3629 itr.Close() 3630 case <-itr.done: 3631 } 3632} 3633 3634func (itr *integerCloseInterruptIterator) Stats() IteratorStats { 3635 return itr.input.Stats() 3636} 3637 3638func (itr *integerCloseInterruptIterator) Close() error { 3639 itr.once.Do(func() { 3640 close(itr.done) 3641 itr.input.Close() 3642 }) 3643 return nil 3644} 3645 3646func (itr *integerCloseInterruptIterator) Next() (*IntegerPoint, error) { 3647 p, err := itr.input.Next() 3648 if err != nil { 3649 // Check if the iterator was closed. 3650 select { 3651 case <-itr.done: 3652 return nil, nil 3653 default: 3654 return nil, err 3655 } 3656 } 3657 return p, nil 3658} 3659 3660// integerReduceFloatIterator executes a reducer for every interval and buffers the result. 3661type integerReduceFloatIterator struct { 3662 input *bufIntegerIterator 3663 create func() (IntegerPointAggregator, FloatPointEmitter) 3664 dims []string 3665 opt IteratorOptions 3666 points []FloatPoint 3667 keepTags bool 3668} 3669 3670func newIntegerReduceFloatIterator(input IntegerIterator, opt IteratorOptions, createFn func() (IntegerPointAggregator, FloatPointEmitter)) *integerReduceFloatIterator { 3671 return &integerReduceFloatIterator{ 3672 input: newBufIntegerIterator(input), 3673 create: createFn, 3674 dims: opt.GetDimensions(), 3675 opt: opt, 3676 } 3677} 3678 3679// Stats returns stats from the input iterator. 3680func (itr *integerReduceFloatIterator) Stats() IteratorStats { return itr.input.Stats() } 3681 3682// Close closes the iterator and all child iterators. 3683func (itr *integerReduceFloatIterator) Close() error { return itr.input.Close() } 3684 3685// Next returns the minimum value for the next available interval. 3686func (itr *integerReduceFloatIterator) Next() (*FloatPoint, error) { 3687 // Calculate next window if we have no more points. 3688 if len(itr.points) == 0 { 3689 var err error 3690 itr.points, err = itr.reduce() 3691 if len(itr.points) == 0 { 3692 return nil, err 3693 } 3694 } 3695 3696 // Pop next point off the stack. 3697 p := &itr.points[len(itr.points)-1] 3698 itr.points = itr.points[:len(itr.points)-1] 3699 return p, nil 3700} 3701 3702// integerReduceFloatPoint stores the reduced data for a name/tag combination. 3703type integerReduceFloatPoint struct { 3704 Name string 3705 Tags Tags 3706 Aggregator IntegerPointAggregator 3707 Emitter FloatPointEmitter 3708} 3709 3710// reduce executes fn once for every point in the next window. 3711// The previous value for the dimension is passed to fn. 3712func (itr *integerReduceFloatIterator) reduce() ([]FloatPoint, error) { 3713 // Calculate next window. 3714 var ( 3715 startTime, endTime int64 3716 window struct { 3717 name string 3718 tags string 3719 } 3720 ) 3721 for { 3722 p, err := itr.input.Next() 3723 if err != nil || p == nil { 3724 return nil, err 3725 } else if p.Nil { 3726 continue 3727 } 3728 3729 // Unread the point so it can be processed. 3730 itr.input.unread(p) 3731 startTime, endTime = itr.opt.Window(p.Time) 3732 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 3733 break 3734 } 3735 3736 // Create points by tags. 3737 m := make(map[string]*integerReduceFloatPoint) 3738 for { 3739 // Read next point. 3740 curr, err := itr.input.NextInWindow(startTime, endTime) 3741 if err != nil { 3742 return nil, err 3743 } else if curr == nil { 3744 break 3745 } else if curr.Nil { 3746 continue 3747 } else if curr.Name != window.name { 3748 itr.input.unread(curr) 3749 break 3750 } 3751 3752 // Ensure this point is within the same final window. 3753 if curr.Name != window.name { 3754 itr.input.unread(curr) 3755 break 3756 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 3757 itr.input.unread(curr) 3758 break 3759 } 3760 3761 // Retrieve the tags on this point for this level of the query. 3762 // This may be different than the bucket dimensions. 3763 tags := curr.Tags.Subset(itr.dims) 3764 id := tags.ID() 3765 3766 // Retrieve the aggregator for this name/tag combination or create one. 3767 rp := m[id] 3768 if rp == nil { 3769 aggregator, emitter := itr.create() 3770 rp = &integerReduceFloatPoint{ 3771 Name: curr.Name, 3772 Tags: tags, 3773 Aggregator: aggregator, 3774 Emitter: emitter, 3775 } 3776 m[id] = rp 3777 } 3778 rp.Aggregator.AggregateInteger(curr) 3779 } 3780 3781 keys := make([]string, 0, len(m)) 3782 for k := range m { 3783 keys = append(keys, k) 3784 } 3785 3786 // Reverse sort points by name & tag. 3787 // This ensures a consistent order of output. 3788 if len(keys) > 0 { 3789 var sorted sort.Interface = sort.StringSlice(keys) 3790 if itr.opt.Ascending { 3791 sorted = sort.Reverse(sorted) 3792 } 3793 sort.Sort(sorted) 3794 } 3795 3796 // Assume the points are already sorted until proven otherwise. 3797 sortedByTime := true 3798 // Emit the points for each name & tag combination. 3799 a := make([]FloatPoint, 0, len(m)) 3800 for _, k := range keys { 3801 rp := m[k] 3802 points := rp.Emitter.Emit() 3803 for i := len(points) - 1; i >= 0; i-- { 3804 points[i].Name = rp.Name 3805 if !itr.keepTags { 3806 points[i].Tags = rp.Tags 3807 } 3808 // Set the points time to the interval time if the reducer didn't provide one. 3809 if points[i].Time == ZeroTime { 3810 points[i].Time = startTime 3811 } else { 3812 sortedByTime = false 3813 } 3814 a = append(a, points[i]) 3815 } 3816 } 3817 // Points may be out of order. Perform a stable sort by time if requested. 3818 if !sortedByTime && itr.opt.Ordered { 3819 var sorted sort.Interface = floatPointsByTime(a) 3820 if itr.opt.Ascending { 3821 sorted = sort.Reverse(sorted) 3822 } 3823 sort.Stable(sorted) 3824 } 3825 return a, nil 3826} 3827 3828// integerStreamFloatIterator streams inputs into the iterator and emits points gradually. 3829type integerStreamFloatIterator struct { 3830 input *bufIntegerIterator 3831 create func() (IntegerPointAggregator, FloatPointEmitter) 3832 dims []string 3833 opt IteratorOptions 3834 m map[string]*integerReduceFloatPoint 3835 points []FloatPoint 3836} 3837 3838// newIntegerStreamFloatIterator returns a new instance of integerStreamFloatIterator. 3839func newIntegerStreamFloatIterator(input IntegerIterator, createFn func() (IntegerPointAggregator, FloatPointEmitter), opt IteratorOptions) *integerStreamFloatIterator { 3840 return &integerStreamFloatIterator{ 3841 input: newBufIntegerIterator(input), 3842 create: createFn, 3843 dims: opt.GetDimensions(), 3844 opt: opt, 3845 m: make(map[string]*integerReduceFloatPoint), 3846 } 3847} 3848 3849// Stats returns stats from the input iterator. 3850func (itr *integerStreamFloatIterator) Stats() IteratorStats { return itr.input.Stats() } 3851 3852// Close closes the iterator and all child iterators. 3853func (itr *integerStreamFloatIterator) Close() error { return itr.input.Close() } 3854 3855// Next returns the next value for the stream iterator. 3856func (itr *integerStreamFloatIterator) Next() (*FloatPoint, error) { 3857 // Calculate next window if we have no more points. 3858 if len(itr.points) == 0 { 3859 var err error 3860 itr.points, err = itr.reduce() 3861 if len(itr.points) == 0 { 3862 return nil, err 3863 } 3864 } 3865 3866 // Pop next point off the stack. 3867 p := &itr.points[len(itr.points)-1] 3868 itr.points = itr.points[:len(itr.points)-1] 3869 return p, nil 3870} 3871 3872// reduce creates and manages aggregators for every point from the input. 3873// After aggregating a point, it always tries to emit a value using the emitter. 3874func (itr *integerStreamFloatIterator) reduce() ([]FloatPoint, error) { 3875 // We have already read all of the input points. 3876 if itr.m == nil { 3877 return nil, nil 3878 } 3879 3880 for { 3881 // Read next point. 3882 curr, err := itr.input.Next() 3883 if err != nil { 3884 return nil, err 3885 } else if curr == nil { 3886 // Close all of the aggregators to flush any remaining points to emit. 3887 var points []FloatPoint 3888 for _, rp := range itr.m { 3889 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 3890 if err := aggregator.Close(); err != nil { 3891 return nil, err 3892 } 3893 3894 pts := rp.Emitter.Emit() 3895 if len(pts) == 0 { 3896 continue 3897 } 3898 3899 for i := range pts { 3900 pts[i].Name = rp.Name 3901 pts[i].Tags = rp.Tags 3902 } 3903 points = append(points, pts...) 3904 } 3905 } 3906 3907 // Eliminate the aggregators and emitters. 3908 itr.m = nil 3909 return points, nil 3910 } else if curr.Nil { 3911 continue 3912 } 3913 tags := curr.Tags.Subset(itr.dims) 3914 3915 id := curr.Name 3916 if len(tags.m) > 0 { 3917 id += "\x00" + tags.ID() 3918 } 3919 3920 // Retrieve the aggregator for this name/tag combination or create one. 3921 rp := itr.m[id] 3922 if rp == nil { 3923 aggregator, emitter := itr.create() 3924 rp = &integerReduceFloatPoint{ 3925 Name: curr.Name, 3926 Tags: tags, 3927 Aggregator: aggregator, 3928 Emitter: emitter, 3929 } 3930 itr.m[id] = rp 3931 } 3932 rp.Aggregator.AggregateInteger(curr) 3933 3934 // Attempt to emit points from the aggregator. 3935 points := rp.Emitter.Emit() 3936 if len(points) == 0 { 3937 continue 3938 } 3939 3940 for i := range points { 3941 points[i].Name = rp.Name 3942 points[i].Tags = rp.Tags 3943 } 3944 return points, nil 3945 } 3946} 3947 3948// integerReduceIntegerIterator executes a reducer for every interval and buffers the result. 3949type integerReduceIntegerIterator struct { 3950 input *bufIntegerIterator 3951 create func() (IntegerPointAggregator, IntegerPointEmitter) 3952 dims []string 3953 opt IteratorOptions 3954 points []IntegerPoint 3955 keepTags bool 3956} 3957 3958func newIntegerReduceIntegerIterator(input IntegerIterator, opt IteratorOptions, createFn func() (IntegerPointAggregator, IntegerPointEmitter)) *integerReduceIntegerIterator { 3959 return &integerReduceIntegerIterator{ 3960 input: newBufIntegerIterator(input), 3961 create: createFn, 3962 dims: opt.GetDimensions(), 3963 opt: opt, 3964 } 3965} 3966 3967// Stats returns stats from the input iterator. 3968func (itr *integerReduceIntegerIterator) Stats() IteratorStats { return itr.input.Stats() } 3969 3970// Close closes the iterator and all child iterators. 3971func (itr *integerReduceIntegerIterator) Close() error { return itr.input.Close() } 3972 3973// Next returns the minimum value for the next available interval. 3974func (itr *integerReduceIntegerIterator) Next() (*IntegerPoint, error) { 3975 // Calculate next window if we have no more points. 3976 if len(itr.points) == 0 { 3977 var err error 3978 itr.points, err = itr.reduce() 3979 if len(itr.points) == 0 { 3980 return nil, err 3981 } 3982 } 3983 3984 // Pop next point off the stack. 3985 p := &itr.points[len(itr.points)-1] 3986 itr.points = itr.points[:len(itr.points)-1] 3987 return p, nil 3988} 3989 3990// integerReduceIntegerPoint stores the reduced data for a name/tag combination. 3991type integerReduceIntegerPoint struct { 3992 Name string 3993 Tags Tags 3994 Aggregator IntegerPointAggregator 3995 Emitter IntegerPointEmitter 3996} 3997 3998// reduce executes fn once for every point in the next window. 3999// The previous value for the dimension is passed to fn. 4000func (itr *integerReduceIntegerIterator) reduce() ([]IntegerPoint, error) { 4001 // Calculate next window. 4002 var ( 4003 startTime, endTime int64 4004 window struct { 4005 name string 4006 tags string 4007 } 4008 ) 4009 for { 4010 p, err := itr.input.Next() 4011 if err != nil || p == nil { 4012 return nil, err 4013 } else if p.Nil { 4014 continue 4015 } 4016 4017 // Unread the point so it can be processed. 4018 itr.input.unread(p) 4019 startTime, endTime = itr.opt.Window(p.Time) 4020 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 4021 break 4022 } 4023 4024 // Create points by tags. 4025 m := make(map[string]*integerReduceIntegerPoint) 4026 for { 4027 // Read next point. 4028 curr, err := itr.input.NextInWindow(startTime, endTime) 4029 if err != nil { 4030 return nil, err 4031 } else if curr == nil { 4032 break 4033 } else if curr.Nil { 4034 continue 4035 } else if curr.Name != window.name { 4036 itr.input.unread(curr) 4037 break 4038 } 4039 4040 // Ensure this point is within the same final window. 4041 if curr.Name != window.name { 4042 itr.input.unread(curr) 4043 break 4044 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 4045 itr.input.unread(curr) 4046 break 4047 } 4048 4049 // Retrieve the tags on this point for this level of the query. 4050 // This may be different than the bucket dimensions. 4051 tags := curr.Tags.Subset(itr.dims) 4052 id := tags.ID() 4053 4054 // Retrieve the aggregator for this name/tag combination or create one. 4055 rp := m[id] 4056 if rp == nil { 4057 aggregator, emitter := itr.create() 4058 rp = &integerReduceIntegerPoint{ 4059 Name: curr.Name, 4060 Tags: tags, 4061 Aggregator: aggregator, 4062 Emitter: emitter, 4063 } 4064 m[id] = rp 4065 } 4066 rp.Aggregator.AggregateInteger(curr) 4067 } 4068 4069 keys := make([]string, 0, len(m)) 4070 for k := range m { 4071 keys = append(keys, k) 4072 } 4073 4074 // Reverse sort points by name & tag. 4075 // This ensures a consistent order of output. 4076 if len(keys) > 0 { 4077 var sorted sort.Interface = sort.StringSlice(keys) 4078 if itr.opt.Ascending { 4079 sorted = sort.Reverse(sorted) 4080 } 4081 sort.Sort(sorted) 4082 } 4083 4084 // Assume the points are already sorted until proven otherwise. 4085 sortedByTime := true 4086 // Emit the points for each name & tag combination. 4087 a := make([]IntegerPoint, 0, len(m)) 4088 for _, k := range keys { 4089 rp := m[k] 4090 points := rp.Emitter.Emit() 4091 for i := len(points) - 1; i >= 0; i-- { 4092 points[i].Name = rp.Name 4093 if !itr.keepTags { 4094 points[i].Tags = rp.Tags 4095 } 4096 // Set the points time to the interval time if the reducer didn't provide one. 4097 if points[i].Time == ZeroTime { 4098 points[i].Time = startTime 4099 } else { 4100 sortedByTime = false 4101 } 4102 a = append(a, points[i]) 4103 } 4104 } 4105 // Points may be out of order. Perform a stable sort by time if requested. 4106 if !sortedByTime && itr.opt.Ordered { 4107 var sorted sort.Interface = integerPointsByTime(a) 4108 if itr.opt.Ascending { 4109 sorted = sort.Reverse(sorted) 4110 } 4111 sort.Stable(sorted) 4112 } 4113 return a, nil 4114} 4115 4116// integerStreamIntegerIterator streams inputs into the iterator and emits points gradually. 4117type integerStreamIntegerIterator struct { 4118 input *bufIntegerIterator 4119 create func() (IntegerPointAggregator, IntegerPointEmitter) 4120 dims []string 4121 opt IteratorOptions 4122 m map[string]*integerReduceIntegerPoint 4123 points []IntegerPoint 4124} 4125 4126// newIntegerStreamIntegerIterator returns a new instance of integerStreamIntegerIterator. 4127func newIntegerStreamIntegerIterator(input IntegerIterator, createFn func() (IntegerPointAggregator, IntegerPointEmitter), opt IteratorOptions) *integerStreamIntegerIterator { 4128 return &integerStreamIntegerIterator{ 4129 input: newBufIntegerIterator(input), 4130 create: createFn, 4131 dims: opt.GetDimensions(), 4132 opt: opt, 4133 m: make(map[string]*integerReduceIntegerPoint), 4134 } 4135} 4136 4137// Stats returns stats from the input iterator. 4138func (itr *integerStreamIntegerIterator) Stats() IteratorStats { return itr.input.Stats() } 4139 4140// Close closes the iterator and all child iterators. 4141func (itr *integerStreamIntegerIterator) Close() error { return itr.input.Close() } 4142 4143// Next returns the next value for the stream iterator. 4144func (itr *integerStreamIntegerIterator) Next() (*IntegerPoint, error) { 4145 // Calculate next window if we have no more points. 4146 if len(itr.points) == 0 { 4147 var err error 4148 itr.points, err = itr.reduce() 4149 if len(itr.points) == 0 { 4150 return nil, err 4151 } 4152 } 4153 4154 // Pop next point off the stack. 4155 p := &itr.points[len(itr.points)-1] 4156 itr.points = itr.points[:len(itr.points)-1] 4157 return p, nil 4158} 4159 4160// reduce creates and manages aggregators for every point from the input. 4161// After aggregating a point, it always tries to emit a value using the emitter. 4162func (itr *integerStreamIntegerIterator) reduce() ([]IntegerPoint, error) { 4163 // We have already read all of the input points. 4164 if itr.m == nil { 4165 return nil, nil 4166 } 4167 4168 for { 4169 // Read next point. 4170 curr, err := itr.input.Next() 4171 if err != nil { 4172 return nil, err 4173 } else if curr == nil { 4174 // Close all of the aggregators to flush any remaining points to emit. 4175 var points []IntegerPoint 4176 for _, rp := range itr.m { 4177 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 4178 if err := aggregator.Close(); err != nil { 4179 return nil, err 4180 } 4181 4182 pts := rp.Emitter.Emit() 4183 if len(pts) == 0 { 4184 continue 4185 } 4186 4187 for i := range pts { 4188 pts[i].Name = rp.Name 4189 pts[i].Tags = rp.Tags 4190 } 4191 points = append(points, pts...) 4192 } 4193 } 4194 4195 // Eliminate the aggregators and emitters. 4196 itr.m = nil 4197 return points, nil 4198 } else if curr.Nil { 4199 continue 4200 } 4201 tags := curr.Tags.Subset(itr.dims) 4202 4203 id := curr.Name 4204 if len(tags.m) > 0 { 4205 id += "\x00" + tags.ID() 4206 } 4207 4208 // Retrieve the aggregator for this name/tag combination or create one. 4209 rp := itr.m[id] 4210 if rp == nil { 4211 aggregator, emitter := itr.create() 4212 rp = &integerReduceIntegerPoint{ 4213 Name: curr.Name, 4214 Tags: tags, 4215 Aggregator: aggregator, 4216 Emitter: emitter, 4217 } 4218 itr.m[id] = rp 4219 } 4220 rp.Aggregator.AggregateInteger(curr) 4221 4222 // Attempt to emit points from the aggregator. 4223 points := rp.Emitter.Emit() 4224 if len(points) == 0 { 4225 continue 4226 } 4227 4228 for i := range points { 4229 points[i].Name = rp.Name 4230 points[i].Tags = rp.Tags 4231 } 4232 return points, nil 4233 } 4234} 4235 4236// integerReduceUnsignedIterator executes a reducer for every interval and buffers the result. 4237type integerReduceUnsignedIterator struct { 4238 input *bufIntegerIterator 4239 create func() (IntegerPointAggregator, UnsignedPointEmitter) 4240 dims []string 4241 opt IteratorOptions 4242 points []UnsignedPoint 4243 keepTags bool 4244} 4245 4246func newIntegerReduceUnsignedIterator(input IntegerIterator, opt IteratorOptions, createFn func() (IntegerPointAggregator, UnsignedPointEmitter)) *integerReduceUnsignedIterator { 4247 return &integerReduceUnsignedIterator{ 4248 input: newBufIntegerIterator(input), 4249 create: createFn, 4250 dims: opt.GetDimensions(), 4251 opt: opt, 4252 } 4253} 4254 4255// Stats returns stats from the input iterator. 4256func (itr *integerReduceUnsignedIterator) Stats() IteratorStats { return itr.input.Stats() } 4257 4258// Close closes the iterator and all child iterators. 4259func (itr *integerReduceUnsignedIterator) Close() error { return itr.input.Close() } 4260 4261// Next returns the minimum value for the next available interval. 4262func (itr *integerReduceUnsignedIterator) Next() (*UnsignedPoint, error) { 4263 // Calculate next window if we have no more points. 4264 if len(itr.points) == 0 { 4265 var err error 4266 itr.points, err = itr.reduce() 4267 if len(itr.points) == 0 { 4268 return nil, err 4269 } 4270 } 4271 4272 // Pop next point off the stack. 4273 p := &itr.points[len(itr.points)-1] 4274 itr.points = itr.points[:len(itr.points)-1] 4275 return p, nil 4276} 4277 4278// integerReduceUnsignedPoint stores the reduced data for a name/tag combination. 4279type integerReduceUnsignedPoint struct { 4280 Name string 4281 Tags Tags 4282 Aggregator IntegerPointAggregator 4283 Emitter UnsignedPointEmitter 4284} 4285 4286// reduce executes fn once for every point in the next window. 4287// The previous value for the dimension is passed to fn. 4288func (itr *integerReduceUnsignedIterator) reduce() ([]UnsignedPoint, error) { 4289 // Calculate next window. 4290 var ( 4291 startTime, endTime int64 4292 window struct { 4293 name string 4294 tags string 4295 } 4296 ) 4297 for { 4298 p, err := itr.input.Next() 4299 if err != nil || p == nil { 4300 return nil, err 4301 } else if p.Nil { 4302 continue 4303 } 4304 4305 // Unread the point so it can be processed. 4306 itr.input.unread(p) 4307 startTime, endTime = itr.opt.Window(p.Time) 4308 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 4309 break 4310 } 4311 4312 // Create points by tags. 4313 m := make(map[string]*integerReduceUnsignedPoint) 4314 for { 4315 // Read next point. 4316 curr, err := itr.input.NextInWindow(startTime, endTime) 4317 if err != nil { 4318 return nil, err 4319 } else if curr == nil { 4320 break 4321 } else if curr.Nil { 4322 continue 4323 } else if curr.Name != window.name { 4324 itr.input.unread(curr) 4325 break 4326 } 4327 4328 // Ensure this point is within the same final window. 4329 if curr.Name != window.name { 4330 itr.input.unread(curr) 4331 break 4332 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 4333 itr.input.unread(curr) 4334 break 4335 } 4336 4337 // Retrieve the tags on this point for this level of the query. 4338 // This may be different than the bucket dimensions. 4339 tags := curr.Tags.Subset(itr.dims) 4340 id := tags.ID() 4341 4342 // Retrieve the aggregator for this name/tag combination or create one. 4343 rp := m[id] 4344 if rp == nil { 4345 aggregator, emitter := itr.create() 4346 rp = &integerReduceUnsignedPoint{ 4347 Name: curr.Name, 4348 Tags: tags, 4349 Aggregator: aggregator, 4350 Emitter: emitter, 4351 } 4352 m[id] = rp 4353 } 4354 rp.Aggregator.AggregateInteger(curr) 4355 } 4356 4357 keys := make([]string, 0, len(m)) 4358 for k := range m { 4359 keys = append(keys, k) 4360 } 4361 4362 // Reverse sort points by name & tag. 4363 // This ensures a consistent order of output. 4364 if len(keys) > 0 { 4365 var sorted sort.Interface = sort.StringSlice(keys) 4366 if itr.opt.Ascending { 4367 sorted = sort.Reverse(sorted) 4368 } 4369 sort.Sort(sorted) 4370 } 4371 4372 // Assume the points are already sorted until proven otherwise. 4373 sortedByTime := true 4374 // Emit the points for each name & tag combination. 4375 a := make([]UnsignedPoint, 0, len(m)) 4376 for _, k := range keys { 4377 rp := m[k] 4378 points := rp.Emitter.Emit() 4379 for i := len(points) - 1; i >= 0; i-- { 4380 points[i].Name = rp.Name 4381 if !itr.keepTags { 4382 points[i].Tags = rp.Tags 4383 } 4384 // Set the points time to the interval time if the reducer didn't provide one. 4385 if points[i].Time == ZeroTime { 4386 points[i].Time = startTime 4387 } else { 4388 sortedByTime = false 4389 } 4390 a = append(a, points[i]) 4391 } 4392 } 4393 // Points may be out of order. Perform a stable sort by time if requested. 4394 if !sortedByTime && itr.opt.Ordered { 4395 var sorted sort.Interface = unsignedPointsByTime(a) 4396 if itr.opt.Ascending { 4397 sorted = sort.Reverse(sorted) 4398 } 4399 sort.Stable(sorted) 4400 } 4401 return a, nil 4402} 4403 4404// integerStreamUnsignedIterator streams inputs into the iterator and emits points gradually. 4405type integerStreamUnsignedIterator struct { 4406 input *bufIntegerIterator 4407 create func() (IntegerPointAggregator, UnsignedPointEmitter) 4408 dims []string 4409 opt IteratorOptions 4410 m map[string]*integerReduceUnsignedPoint 4411 points []UnsignedPoint 4412} 4413 4414// newIntegerStreamUnsignedIterator returns a new instance of integerStreamUnsignedIterator. 4415func newIntegerStreamUnsignedIterator(input IntegerIterator, createFn func() (IntegerPointAggregator, UnsignedPointEmitter), opt IteratorOptions) *integerStreamUnsignedIterator { 4416 return &integerStreamUnsignedIterator{ 4417 input: newBufIntegerIterator(input), 4418 create: createFn, 4419 dims: opt.GetDimensions(), 4420 opt: opt, 4421 m: make(map[string]*integerReduceUnsignedPoint), 4422 } 4423} 4424 4425// Stats returns stats from the input iterator. 4426func (itr *integerStreamUnsignedIterator) Stats() IteratorStats { return itr.input.Stats() } 4427 4428// Close closes the iterator and all child iterators. 4429func (itr *integerStreamUnsignedIterator) Close() error { return itr.input.Close() } 4430 4431// Next returns the next value for the stream iterator. 4432func (itr *integerStreamUnsignedIterator) Next() (*UnsignedPoint, error) { 4433 // Calculate next window if we have no more points. 4434 if len(itr.points) == 0 { 4435 var err error 4436 itr.points, err = itr.reduce() 4437 if len(itr.points) == 0 { 4438 return nil, err 4439 } 4440 } 4441 4442 // Pop next point off the stack. 4443 p := &itr.points[len(itr.points)-1] 4444 itr.points = itr.points[:len(itr.points)-1] 4445 return p, nil 4446} 4447 4448// reduce creates and manages aggregators for every point from the input. 4449// After aggregating a point, it always tries to emit a value using the emitter. 4450func (itr *integerStreamUnsignedIterator) reduce() ([]UnsignedPoint, error) { 4451 // We have already read all of the input points. 4452 if itr.m == nil { 4453 return nil, nil 4454 } 4455 4456 for { 4457 // Read next point. 4458 curr, err := itr.input.Next() 4459 if err != nil { 4460 return nil, err 4461 } else if curr == nil { 4462 // Close all of the aggregators to flush any remaining points to emit. 4463 var points []UnsignedPoint 4464 for _, rp := range itr.m { 4465 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 4466 if err := aggregator.Close(); err != nil { 4467 return nil, err 4468 } 4469 4470 pts := rp.Emitter.Emit() 4471 if len(pts) == 0 { 4472 continue 4473 } 4474 4475 for i := range pts { 4476 pts[i].Name = rp.Name 4477 pts[i].Tags = rp.Tags 4478 } 4479 points = append(points, pts...) 4480 } 4481 } 4482 4483 // Eliminate the aggregators and emitters. 4484 itr.m = nil 4485 return points, nil 4486 } else if curr.Nil { 4487 continue 4488 } 4489 tags := curr.Tags.Subset(itr.dims) 4490 4491 id := curr.Name 4492 if len(tags.m) > 0 { 4493 id += "\x00" + tags.ID() 4494 } 4495 4496 // Retrieve the aggregator for this name/tag combination or create one. 4497 rp := itr.m[id] 4498 if rp == nil { 4499 aggregator, emitter := itr.create() 4500 rp = &integerReduceUnsignedPoint{ 4501 Name: curr.Name, 4502 Tags: tags, 4503 Aggregator: aggregator, 4504 Emitter: emitter, 4505 } 4506 itr.m[id] = rp 4507 } 4508 rp.Aggregator.AggregateInteger(curr) 4509 4510 // Attempt to emit points from the aggregator. 4511 points := rp.Emitter.Emit() 4512 if len(points) == 0 { 4513 continue 4514 } 4515 4516 for i := range points { 4517 points[i].Name = rp.Name 4518 points[i].Tags = rp.Tags 4519 } 4520 return points, nil 4521 } 4522} 4523 4524// integerReduceStringIterator executes a reducer for every interval and buffers the result. 4525type integerReduceStringIterator struct { 4526 input *bufIntegerIterator 4527 create func() (IntegerPointAggregator, StringPointEmitter) 4528 dims []string 4529 opt IteratorOptions 4530 points []StringPoint 4531 keepTags bool 4532} 4533 4534func newIntegerReduceStringIterator(input IntegerIterator, opt IteratorOptions, createFn func() (IntegerPointAggregator, StringPointEmitter)) *integerReduceStringIterator { 4535 return &integerReduceStringIterator{ 4536 input: newBufIntegerIterator(input), 4537 create: createFn, 4538 dims: opt.GetDimensions(), 4539 opt: opt, 4540 } 4541} 4542 4543// Stats returns stats from the input iterator. 4544func (itr *integerReduceStringIterator) Stats() IteratorStats { return itr.input.Stats() } 4545 4546// Close closes the iterator and all child iterators. 4547func (itr *integerReduceStringIterator) Close() error { return itr.input.Close() } 4548 4549// Next returns the minimum value for the next available interval. 4550func (itr *integerReduceStringIterator) Next() (*StringPoint, error) { 4551 // Calculate next window if we have no more points. 4552 if len(itr.points) == 0 { 4553 var err error 4554 itr.points, err = itr.reduce() 4555 if len(itr.points) == 0 { 4556 return nil, err 4557 } 4558 } 4559 4560 // Pop next point off the stack. 4561 p := &itr.points[len(itr.points)-1] 4562 itr.points = itr.points[:len(itr.points)-1] 4563 return p, nil 4564} 4565 4566// integerReduceStringPoint stores the reduced data for a name/tag combination. 4567type integerReduceStringPoint struct { 4568 Name string 4569 Tags Tags 4570 Aggregator IntegerPointAggregator 4571 Emitter StringPointEmitter 4572} 4573 4574// reduce executes fn once for every point in the next window. 4575// The previous value for the dimension is passed to fn. 4576func (itr *integerReduceStringIterator) reduce() ([]StringPoint, error) { 4577 // Calculate next window. 4578 var ( 4579 startTime, endTime int64 4580 window struct { 4581 name string 4582 tags string 4583 } 4584 ) 4585 for { 4586 p, err := itr.input.Next() 4587 if err != nil || p == nil { 4588 return nil, err 4589 } else if p.Nil { 4590 continue 4591 } 4592 4593 // Unread the point so it can be processed. 4594 itr.input.unread(p) 4595 startTime, endTime = itr.opt.Window(p.Time) 4596 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 4597 break 4598 } 4599 4600 // Create points by tags. 4601 m := make(map[string]*integerReduceStringPoint) 4602 for { 4603 // Read next point. 4604 curr, err := itr.input.NextInWindow(startTime, endTime) 4605 if err != nil { 4606 return nil, err 4607 } else if curr == nil { 4608 break 4609 } else if curr.Nil { 4610 continue 4611 } else if curr.Name != window.name { 4612 itr.input.unread(curr) 4613 break 4614 } 4615 4616 // Ensure this point is within the same final window. 4617 if curr.Name != window.name { 4618 itr.input.unread(curr) 4619 break 4620 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 4621 itr.input.unread(curr) 4622 break 4623 } 4624 4625 // Retrieve the tags on this point for this level of the query. 4626 // This may be different than the bucket dimensions. 4627 tags := curr.Tags.Subset(itr.dims) 4628 id := tags.ID() 4629 4630 // Retrieve the aggregator for this name/tag combination or create one. 4631 rp := m[id] 4632 if rp == nil { 4633 aggregator, emitter := itr.create() 4634 rp = &integerReduceStringPoint{ 4635 Name: curr.Name, 4636 Tags: tags, 4637 Aggregator: aggregator, 4638 Emitter: emitter, 4639 } 4640 m[id] = rp 4641 } 4642 rp.Aggregator.AggregateInteger(curr) 4643 } 4644 4645 keys := make([]string, 0, len(m)) 4646 for k := range m { 4647 keys = append(keys, k) 4648 } 4649 4650 // Reverse sort points by name & tag. 4651 // This ensures a consistent order of output. 4652 if len(keys) > 0 { 4653 var sorted sort.Interface = sort.StringSlice(keys) 4654 if itr.opt.Ascending { 4655 sorted = sort.Reverse(sorted) 4656 } 4657 sort.Sort(sorted) 4658 } 4659 4660 // Assume the points are already sorted until proven otherwise. 4661 sortedByTime := true 4662 // Emit the points for each name & tag combination. 4663 a := make([]StringPoint, 0, len(m)) 4664 for _, k := range keys { 4665 rp := m[k] 4666 points := rp.Emitter.Emit() 4667 for i := len(points) - 1; i >= 0; i-- { 4668 points[i].Name = rp.Name 4669 if !itr.keepTags { 4670 points[i].Tags = rp.Tags 4671 } 4672 // Set the points time to the interval time if the reducer didn't provide one. 4673 if points[i].Time == ZeroTime { 4674 points[i].Time = startTime 4675 } else { 4676 sortedByTime = false 4677 } 4678 a = append(a, points[i]) 4679 } 4680 } 4681 // Points may be out of order. Perform a stable sort by time if requested. 4682 if !sortedByTime && itr.opt.Ordered { 4683 var sorted sort.Interface = stringPointsByTime(a) 4684 if itr.opt.Ascending { 4685 sorted = sort.Reverse(sorted) 4686 } 4687 sort.Stable(sorted) 4688 } 4689 return a, nil 4690} 4691 4692// integerStreamStringIterator streams inputs into the iterator and emits points gradually. 4693type integerStreamStringIterator struct { 4694 input *bufIntegerIterator 4695 create func() (IntegerPointAggregator, StringPointEmitter) 4696 dims []string 4697 opt IteratorOptions 4698 m map[string]*integerReduceStringPoint 4699 points []StringPoint 4700} 4701 4702// newIntegerStreamStringIterator returns a new instance of integerStreamStringIterator. 4703func newIntegerStreamStringIterator(input IntegerIterator, createFn func() (IntegerPointAggregator, StringPointEmitter), opt IteratorOptions) *integerStreamStringIterator { 4704 return &integerStreamStringIterator{ 4705 input: newBufIntegerIterator(input), 4706 create: createFn, 4707 dims: opt.GetDimensions(), 4708 opt: opt, 4709 m: make(map[string]*integerReduceStringPoint), 4710 } 4711} 4712 4713// Stats returns stats from the input iterator. 4714func (itr *integerStreamStringIterator) Stats() IteratorStats { return itr.input.Stats() } 4715 4716// Close closes the iterator and all child iterators. 4717func (itr *integerStreamStringIterator) Close() error { return itr.input.Close() } 4718 4719// Next returns the next value for the stream iterator. 4720func (itr *integerStreamStringIterator) Next() (*StringPoint, error) { 4721 // Calculate next window if we have no more points. 4722 if len(itr.points) == 0 { 4723 var err error 4724 itr.points, err = itr.reduce() 4725 if len(itr.points) == 0 { 4726 return nil, err 4727 } 4728 } 4729 4730 // Pop next point off the stack. 4731 p := &itr.points[len(itr.points)-1] 4732 itr.points = itr.points[:len(itr.points)-1] 4733 return p, nil 4734} 4735 4736// reduce creates and manages aggregators for every point from the input. 4737// After aggregating a point, it always tries to emit a value using the emitter. 4738func (itr *integerStreamStringIterator) reduce() ([]StringPoint, error) { 4739 // We have already read all of the input points. 4740 if itr.m == nil { 4741 return nil, nil 4742 } 4743 4744 for { 4745 // Read next point. 4746 curr, err := itr.input.Next() 4747 if err != nil { 4748 return nil, err 4749 } else if curr == nil { 4750 // Close all of the aggregators to flush any remaining points to emit. 4751 var points []StringPoint 4752 for _, rp := range itr.m { 4753 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 4754 if err := aggregator.Close(); err != nil { 4755 return nil, err 4756 } 4757 4758 pts := rp.Emitter.Emit() 4759 if len(pts) == 0 { 4760 continue 4761 } 4762 4763 for i := range pts { 4764 pts[i].Name = rp.Name 4765 pts[i].Tags = rp.Tags 4766 } 4767 points = append(points, pts...) 4768 } 4769 } 4770 4771 // Eliminate the aggregators and emitters. 4772 itr.m = nil 4773 return points, nil 4774 } else if curr.Nil { 4775 continue 4776 } 4777 tags := curr.Tags.Subset(itr.dims) 4778 4779 id := curr.Name 4780 if len(tags.m) > 0 { 4781 id += "\x00" + tags.ID() 4782 } 4783 4784 // Retrieve the aggregator for this name/tag combination or create one. 4785 rp := itr.m[id] 4786 if rp == nil { 4787 aggregator, emitter := itr.create() 4788 rp = &integerReduceStringPoint{ 4789 Name: curr.Name, 4790 Tags: tags, 4791 Aggregator: aggregator, 4792 Emitter: emitter, 4793 } 4794 itr.m[id] = rp 4795 } 4796 rp.Aggregator.AggregateInteger(curr) 4797 4798 // Attempt to emit points from the aggregator. 4799 points := rp.Emitter.Emit() 4800 if len(points) == 0 { 4801 continue 4802 } 4803 4804 for i := range points { 4805 points[i].Name = rp.Name 4806 points[i].Tags = rp.Tags 4807 } 4808 return points, nil 4809 } 4810} 4811 4812// integerReduceBooleanIterator executes a reducer for every interval and buffers the result. 4813type integerReduceBooleanIterator struct { 4814 input *bufIntegerIterator 4815 create func() (IntegerPointAggregator, BooleanPointEmitter) 4816 dims []string 4817 opt IteratorOptions 4818 points []BooleanPoint 4819 keepTags bool 4820} 4821 4822func newIntegerReduceBooleanIterator(input IntegerIterator, opt IteratorOptions, createFn func() (IntegerPointAggregator, BooleanPointEmitter)) *integerReduceBooleanIterator { 4823 return &integerReduceBooleanIterator{ 4824 input: newBufIntegerIterator(input), 4825 create: createFn, 4826 dims: opt.GetDimensions(), 4827 opt: opt, 4828 } 4829} 4830 4831// Stats returns stats from the input iterator. 4832func (itr *integerReduceBooleanIterator) Stats() IteratorStats { return itr.input.Stats() } 4833 4834// Close closes the iterator and all child iterators. 4835func (itr *integerReduceBooleanIterator) Close() error { return itr.input.Close() } 4836 4837// Next returns the minimum value for the next available interval. 4838func (itr *integerReduceBooleanIterator) Next() (*BooleanPoint, error) { 4839 // Calculate next window if we have no more points. 4840 if len(itr.points) == 0 { 4841 var err error 4842 itr.points, err = itr.reduce() 4843 if len(itr.points) == 0 { 4844 return nil, err 4845 } 4846 } 4847 4848 // Pop next point off the stack. 4849 p := &itr.points[len(itr.points)-1] 4850 itr.points = itr.points[:len(itr.points)-1] 4851 return p, nil 4852} 4853 4854// integerReduceBooleanPoint stores the reduced data for a name/tag combination. 4855type integerReduceBooleanPoint struct { 4856 Name string 4857 Tags Tags 4858 Aggregator IntegerPointAggregator 4859 Emitter BooleanPointEmitter 4860} 4861 4862// reduce executes fn once for every point in the next window. 4863// The previous value for the dimension is passed to fn. 4864func (itr *integerReduceBooleanIterator) reduce() ([]BooleanPoint, error) { 4865 // Calculate next window. 4866 var ( 4867 startTime, endTime int64 4868 window struct { 4869 name string 4870 tags string 4871 } 4872 ) 4873 for { 4874 p, err := itr.input.Next() 4875 if err != nil || p == nil { 4876 return nil, err 4877 } else if p.Nil { 4878 continue 4879 } 4880 4881 // Unread the point so it can be processed. 4882 itr.input.unread(p) 4883 startTime, endTime = itr.opt.Window(p.Time) 4884 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 4885 break 4886 } 4887 4888 // Create points by tags. 4889 m := make(map[string]*integerReduceBooleanPoint) 4890 for { 4891 // Read next point. 4892 curr, err := itr.input.NextInWindow(startTime, endTime) 4893 if err != nil { 4894 return nil, err 4895 } else if curr == nil { 4896 break 4897 } else if curr.Nil { 4898 continue 4899 } else if curr.Name != window.name { 4900 itr.input.unread(curr) 4901 break 4902 } 4903 4904 // Ensure this point is within the same final window. 4905 if curr.Name != window.name { 4906 itr.input.unread(curr) 4907 break 4908 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 4909 itr.input.unread(curr) 4910 break 4911 } 4912 4913 // Retrieve the tags on this point for this level of the query. 4914 // This may be different than the bucket dimensions. 4915 tags := curr.Tags.Subset(itr.dims) 4916 id := tags.ID() 4917 4918 // Retrieve the aggregator for this name/tag combination or create one. 4919 rp := m[id] 4920 if rp == nil { 4921 aggregator, emitter := itr.create() 4922 rp = &integerReduceBooleanPoint{ 4923 Name: curr.Name, 4924 Tags: tags, 4925 Aggregator: aggregator, 4926 Emitter: emitter, 4927 } 4928 m[id] = rp 4929 } 4930 rp.Aggregator.AggregateInteger(curr) 4931 } 4932 4933 keys := make([]string, 0, len(m)) 4934 for k := range m { 4935 keys = append(keys, k) 4936 } 4937 4938 // Reverse sort points by name & tag. 4939 // This ensures a consistent order of output. 4940 if len(keys) > 0 { 4941 var sorted sort.Interface = sort.StringSlice(keys) 4942 if itr.opt.Ascending { 4943 sorted = sort.Reverse(sorted) 4944 } 4945 sort.Sort(sorted) 4946 } 4947 4948 // Assume the points are already sorted until proven otherwise. 4949 sortedByTime := true 4950 // Emit the points for each name & tag combination. 4951 a := make([]BooleanPoint, 0, len(m)) 4952 for _, k := range keys { 4953 rp := m[k] 4954 points := rp.Emitter.Emit() 4955 for i := len(points) - 1; i >= 0; i-- { 4956 points[i].Name = rp.Name 4957 if !itr.keepTags { 4958 points[i].Tags = rp.Tags 4959 } 4960 // Set the points time to the interval time if the reducer didn't provide one. 4961 if points[i].Time == ZeroTime { 4962 points[i].Time = startTime 4963 } else { 4964 sortedByTime = false 4965 } 4966 a = append(a, points[i]) 4967 } 4968 } 4969 // Points may be out of order. Perform a stable sort by time if requested. 4970 if !sortedByTime && itr.opt.Ordered { 4971 var sorted sort.Interface = booleanPointsByTime(a) 4972 if itr.opt.Ascending { 4973 sorted = sort.Reverse(sorted) 4974 } 4975 sort.Stable(sorted) 4976 } 4977 return a, nil 4978} 4979 4980// integerStreamBooleanIterator streams inputs into the iterator and emits points gradually. 4981type integerStreamBooleanIterator struct { 4982 input *bufIntegerIterator 4983 create func() (IntegerPointAggregator, BooleanPointEmitter) 4984 dims []string 4985 opt IteratorOptions 4986 m map[string]*integerReduceBooleanPoint 4987 points []BooleanPoint 4988} 4989 4990// newIntegerStreamBooleanIterator returns a new instance of integerStreamBooleanIterator. 4991func newIntegerStreamBooleanIterator(input IntegerIterator, createFn func() (IntegerPointAggregator, BooleanPointEmitter), opt IteratorOptions) *integerStreamBooleanIterator { 4992 return &integerStreamBooleanIterator{ 4993 input: newBufIntegerIterator(input), 4994 create: createFn, 4995 dims: opt.GetDimensions(), 4996 opt: opt, 4997 m: make(map[string]*integerReduceBooleanPoint), 4998 } 4999} 5000 5001// Stats returns stats from the input iterator. 5002func (itr *integerStreamBooleanIterator) Stats() IteratorStats { return itr.input.Stats() } 5003 5004// Close closes the iterator and all child iterators. 5005func (itr *integerStreamBooleanIterator) Close() error { return itr.input.Close() } 5006 5007// Next returns the next value for the stream iterator. 5008func (itr *integerStreamBooleanIterator) Next() (*BooleanPoint, error) { 5009 // Calculate next window if we have no more points. 5010 if len(itr.points) == 0 { 5011 var err error 5012 itr.points, err = itr.reduce() 5013 if len(itr.points) == 0 { 5014 return nil, err 5015 } 5016 } 5017 5018 // Pop next point off the stack. 5019 p := &itr.points[len(itr.points)-1] 5020 itr.points = itr.points[:len(itr.points)-1] 5021 return p, nil 5022} 5023 5024// reduce creates and manages aggregators for every point from the input. 5025// After aggregating a point, it always tries to emit a value using the emitter. 5026func (itr *integerStreamBooleanIterator) reduce() ([]BooleanPoint, error) { 5027 // We have already read all of the input points. 5028 if itr.m == nil { 5029 return nil, nil 5030 } 5031 5032 for { 5033 // Read next point. 5034 curr, err := itr.input.Next() 5035 if err != nil { 5036 return nil, err 5037 } else if curr == nil { 5038 // Close all of the aggregators to flush any remaining points to emit. 5039 var points []BooleanPoint 5040 for _, rp := range itr.m { 5041 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 5042 if err := aggregator.Close(); err != nil { 5043 return nil, err 5044 } 5045 5046 pts := rp.Emitter.Emit() 5047 if len(pts) == 0 { 5048 continue 5049 } 5050 5051 for i := range pts { 5052 pts[i].Name = rp.Name 5053 pts[i].Tags = rp.Tags 5054 } 5055 points = append(points, pts...) 5056 } 5057 } 5058 5059 // Eliminate the aggregators and emitters. 5060 itr.m = nil 5061 return points, nil 5062 } else if curr.Nil { 5063 continue 5064 } 5065 tags := curr.Tags.Subset(itr.dims) 5066 5067 id := curr.Name 5068 if len(tags.m) > 0 { 5069 id += "\x00" + tags.ID() 5070 } 5071 5072 // Retrieve the aggregator for this name/tag combination or create one. 5073 rp := itr.m[id] 5074 if rp == nil { 5075 aggregator, emitter := itr.create() 5076 rp = &integerReduceBooleanPoint{ 5077 Name: curr.Name, 5078 Tags: tags, 5079 Aggregator: aggregator, 5080 Emitter: emitter, 5081 } 5082 itr.m[id] = rp 5083 } 5084 rp.Aggregator.AggregateInteger(curr) 5085 5086 // Attempt to emit points from the aggregator. 5087 points := rp.Emitter.Emit() 5088 if len(points) == 0 { 5089 continue 5090 } 5091 5092 for i := range points { 5093 points[i].Name = rp.Name 5094 points[i].Tags = rp.Tags 5095 } 5096 return points, nil 5097 } 5098} 5099 5100// integerDedupeIterator only outputs unique points. 5101// This differs from the DistinctIterator in that it compares all aux fields too. 5102// This iterator is relatively inefficient and should only be used on small 5103// datasets such as meta query results. 5104type integerDedupeIterator struct { 5105 input IntegerIterator 5106 m map[string]struct{} // lookup of points already sent 5107} 5108 5109type integerIteratorMapper struct { 5110 cur Cursor 5111 row Row 5112 driver IteratorMap // which iterator to use for the primary value, can be nil 5113 fields []IteratorMap // which iterator to use for an aux field 5114 point IntegerPoint 5115} 5116 5117func newIntegerIteratorMapper(cur Cursor, driver IteratorMap, fields []IteratorMap, opt IteratorOptions) *integerIteratorMapper { 5118 return &integerIteratorMapper{ 5119 cur: cur, 5120 driver: driver, 5121 fields: fields, 5122 point: IntegerPoint{ 5123 Aux: make([]interface{}, len(fields)), 5124 }, 5125 } 5126} 5127 5128func (itr *integerIteratorMapper) Next() (*IntegerPoint, error) { 5129 if !itr.cur.Scan(&itr.row) { 5130 if err := itr.cur.Err(); err != nil { 5131 return nil, err 5132 } 5133 return nil, nil 5134 } 5135 5136 itr.point.Time = itr.row.Time 5137 itr.point.Name = itr.row.Series.Name 5138 itr.point.Tags = itr.row.Series.Tags 5139 5140 if itr.driver != nil { 5141 if v := itr.driver.Value(&itr.row); v != nil { 5142 if v, ok := castToInteger(v); ok { 5143 itr.point.Value = v 5144 itr.point.Nil = false 5145 } else { 5146 itr.point.Value = 0 5147 itr.point.Nil = true 5148 } 5149 } else { 5150 itr.point.Value = 0 5151 itr.point.Nil = true 5152 } 5153 } 5154 for i, f := range itr.fields { 5155 itr.point.Aux[i] = f.Value(&itr.row) 5156 } 5157 return &itr.point, nil 5158} 5159 5160func (itr *integerIteratorMapper) Stats() IteratorStats { 5161 return itr.cur.Stats() 5162} 5163 5164func (itr *integerIteratorMapper) Close() error { 5165 return itr.cur.Close() 5166} 5167 5168type integerFilterIterator struct { 5169 input IntegerIterator 5170 cond influxql.Expr 5171 opt IteratorOptions 5172 m map[string]interface{} 5173} 5174 5175func newIntegerFilterIterator(input IntegerIterator, cond influxql.Expr, opt IteratorOptions) IntegerIterator { 5176 // Strip out time conditions from the WHERE clause. 5177 // TODO(jsternberg): This should really be done for us when creating the IteratorOptions struct. 5178 n := influxql.RewriteFunc(influxql.CloneExpr(cond), func(n influxql.Node) influxql.Node { 5179 switch n := n.(type) { 5180 case *influxql.BinaryExpr: 5181 if n.LHS.String() == "time" { 5182 return &influxql.BooleanLiteral{Val: true} 5183 } 5184 } 5185 return n 5186 }) 5187 5188 cond, _ = n.(influxql.Expr) 5189 if cond == nil { 5190 return input 5191 } else if n, ok := cond.(*influxql.BooleanLiteral); ok && n.Val { 5192 return input 5193 } 5194 5195 return &integerFilterIterator{ 5196 input: input, 5197 cond: cond, 5198 opt: opt, 5199 m: make(map[string]interface{}), 5200 } 5201} 5202 5203func (itr *integerFilterIterator) Stats() IteratorStats { return itr.input.Stats() } 5204func (itr *integerFilterIterator) Close() error { return itr.input.Close() } 5205 5206func (itr *integerFilterIterator) Next() (*IntegerPoint, error) { 5207 for { 5208 p, err := itr.input.Next() 5209 if err != nil || p == nil { 5210 return nil, err 5211 } 5212 5213 for i, ref := range itr.opt.Aux { 5214 itr.m[ref.Val] = p.Aux[i] 5215 } 5216 for k, v := range p.Tags.KeyValues() { 5217 itr.m[k] = v 5218 } 5219 5220 if !influxql.EvalBool(itr.cond, itr.m) { 5221 continue 5222 } 5223 return p, nil 5224 } 5225} 5226 5227type integerTagSubsetIterator struct { 5228 input IntegerIterator 5229 point IntegerPoint 5230 lastTags Tags 5231 dimensions []string 5232} 5233 5234func newIntegerTagSubsetIterator(input IntegerIterator, opt IteratorOptions) *integerTagSubsetIterator { 5235 return &integerTagSubsetIterator{ 5236 input: input, 5237 dimensions: opt.GetDimensions(), 5238 } 5239} 5240 5241func (itr *integerTagSubsetIterator) Next() (*IntegerPoint, error) { 5242 p, err := itr.input.Next() 5243 if err != nil { 5244 return nil, err 5245 } else if p == nil { 5246 return nil, nil 5247 } 5248 5249 itr.point.Name = p.Name 5250 if !p.Tags.Equal(itr.lastTags) { 5251 itr.point.Tags = p.Tags.Subset(itr.dimensions) 5252 itr.lastTags = p.Tags 5253 } 5254 itr.point.Time = p.Time 5255 itr.point.Value = p.Value 5256 itr.point.Aux = p.Aux 5257 itr.point.Aggregated = p.Aggregated 5258 itr.point.Nil = p.Nil 5259 return &itr.point, nil 5260} 5261 5262func (itr *integerTagSubsetIterator) Stats() IteratorStats { 5263 return itr.input.Stats() 5264} 5265 5266func (itr *integerTagSubsetIterator) Close() error { 5267 return itr.input.Close() 5268} 5269 5270// newIntegerDedupeIterator returns a new instance of integerDedupeIterator. 5271func newIntegerDedupeIterator(input IntegerIterator) *integerDedupeIterator { 5272 return &integerDedupeIterator{ 5273 input: input, 5274 m: make(map[string]struct{}), 5275 } 5276} 5277 5278// Stats returns stats from the input iterator. 5279func (itr *integerDedupeIterator) Stats() IteratorStats { return itr.input.Stats() } 5280 5281// Close closes the iterator and all child iterators. 5282func (itr *integerDedupeIterator) Close() error { return itr.input.Close() } 5283 5284// Next returns the next unique point from the input iterator. 5285func (itr *integerDedupeIterator) Next() (*IntegerPoint, error) { 5286 for { 5287 // Read next point. 5288 p, err := itr.input.Next() 5289 if p == nil || err != nil { 5290 return nil, err 5291 } 5292 5293 // Serialize to bytes to store in lookup. 5294 buf, err := proto.Marshal(encodeIntegerPoint(p)) 5295 if err != nil { 5296 return nil, err 5297 } 5298 5299 // If the point has already been output then move to the next point. 5300 if _, ok := itr.m[string(buf)]; ok { 5301 continue 5302 } 5303 5304 // Otherwise mark it as emitted and return point. 5305 itr.m[string(buf)] = struct{}{} 5306 return p, nil 5307 } 5308} 5309 5310// integerReaderIterator represents an iterator that streams from a reader. 5311type integerReaderIterator struct { 5312 r io.Reader 5313 dec *IntegerPointDecoder 5314} 5315 5316// newIntegerReaderIterator returns a new instance of integerReaderIterator. 5317func newIntegerReaderIterator(ctx context.Context, r io.Reader, stats IteratorStats) *integerReaderIterator { 5318 dec := NewIntegerPointDecoder(ctx, r) 5319 dec.stats = stats 5320 5321 return &integerReaderIterator{ 5322 r: r, 5323 dec: dec, 5324 } 5325} 5326 5327// Stats returns stats about points processed. 5328func (itr *integerReaderIterator) Stats() IteratorStats { return itr.dec.stats } 5329 5330// Close closes the underlying reader, if applicable. 5331func (itr *integerReaderIterator) Close() error { 5332 if r, ok := itr.r.(io.ReadCloser); ok { 5333 return r.Close() 5334 } 5335 return nil 5336} 5337 5338// Next returns the next point from the iterator. 5339func (itr *integerReaderIterator) Next() (*IntegerPoint, error) { 5340 // OPTIMIZE(benbjohnson): Reuse point on iterator. 5341 5342 // Unmarshal next point. 5343 p := &IntegerPoint{} 5344 if err := itr.dec.DecodeIntegerPoint(p); err == io.EOF { 5345 return nil, nil 5346 } else if err != nil { 5347 return nil, err 5348 } 5349 return p, nil 5350} 5351 5352// UnsignedIterator represents a stream of unsigned points. 5353type UnsignedIterator interface { 5354 Iterator 5355 Next() (*UnsignedPoint, error) 5356} 5357 5358// newUnsignedIterators converts a slice of Iterator to a slice of UnsignedIterator. 5359// Drop and closes any iterator in itrs that is not a UnsignedIterator and cannot 5360// be cast to a UnsignedIterator. 5361func newUnsignedIterators(itrs []Iterator) []UnsignedIterator { 5362 a := make([]UnsignedIterator, 0, len(itrs)) 5363 for _, itr := range itrs { 5364 switch itr := itr.(type) { 5365 case UnsignedIterator: 5366 a = append(a, itr) 5367 default: 5368 itr.Close() 5369 } 5370 } 5371 return a 5372} 5373 5374// bufUnsignedIterator represents a buffered UnsignedIterator. 5375type bufUnsignedIterator struct { 5376 itr UnsignedIterator 5377 buf *UnsignedPoint 5378} 5379 5380// newBufUnsignedIterator returns a buffered UnsignedIterator. 5381func newBufUnsignedIterator(itr UnsignedIterator) *bufUnsignedIterator { 5382 return &bufUnsignedIterator{itr: itr} 5383} 5384 5385// Stats returns statistics from the input iterator. 5386func (itr *bufUnsignedIterator) Stats() IteratorStats { return itr.itr.Stats() } 5387 5388// Close closes the underlying iterator. 5389func (itr *bufUnsignedIterator) Close() error { return itr.itr.Close() } 5390 5391// peek returns the next point without removing it from the iterator. 5392func (itr *bufUnsignedIterator) peek() (*UnsignedPoint, error) { 5393 p, err := itr.Next() 5394 if err != nil { 5395 return nil, err 5396 } 5397 itr.unread(p) 5398 return p, nil 5399} 5400 5401// peekTime returns the time of the next point. 5402// Returns zero time if no more points available. 5403func (itr *bufUnsignedIterator) peekTime() (int64, error) { 5404 p, err := itr.peek() 5405 if p == nil || err != nil { 5406 return ZeroTime, err 5407 } 5408 return p.Time, nil 5409} 5410 5411// Next returns the current buffer, if exists, or calls the underlying iterator. 5412func (itr *bufUnsignedIterator) Next() (*UnsignedPoint, error) { 5413 buf := itr.buf 5414 if buf != nil { 5415 itr.buf = nil 5416 return buf, nil 5417 } 5418 return itr.itr.Next() 5419} 5420 5421// NextInWindow returns the next value if it is between [startTime, endTime). 5422// If the next value is outside the range then it is moved to the buffer. 5423func (itr *bufUnsignedIterator) NextInWindow(startTime, endTime int64) (*UnsignedPoint, error) { 5424 v, err := itr.Next() 5425 if v == nil || err != nil { 5426 return nil, err 5427 } else if t := v.Time; t >= endTime || t < startTime { 5428 itr.unread(v) 5429 return nil, nil 5430 } 5431 return v, nil 5432} 5433 5434// unread sets v to the buffer. It is read on the next call to Next(). 5435func (itr *bufUnsignedIterator) unread(v *UnsignedPoint) { itr.buf = v } 5436 5437// unsignedMergeIterator represents an iterator that combines multiple unsigned iterators. 5438type unsignedMergeIterator struct { 5439 inputs []UnsignedIterator 5440 heap *unsignedMergeHeap 5441 init bool 5442 5443 closed bool 5444 mu sync.RWMutex 5445 5446 // Current iterator and window. 5447 curr *unsignedMergeHeapItem 5448 window struct { 5449 name string 5450 tags string 5451 startTime int64 5452 endTime int64 5453 } 5454} 5455 5456// newUnsignedMergeIterator returns a new instance of unsignedMergeIterator. 5457func newUnsignedMergeIterator(inputs []UnsignedIterator, opt IteratorOptions) *unsignedMergeIterator { 5458 itr := &unsignedMergeIterator{ 5459 inputs: inputs, 5460 heap: &unsignedMergeHeap{ 5461 items: make([]*unsignedMergeHeapItem, 0, len(inputs)), 5462 opt: opt, 5463 }, 5464 } 5465 5466 // Initialize heap items. 5467 for _, input := range inputs { 5468 // Wrap in buffer, ignore any inputs without anymore points. 5469 bufInput := newBufUnsignedIterator(input) 5470 5471 // Append to the heap. 5472 itr.heap.items = append(itr.heap.items, &unsignedMergeHeapItem{itr: bufInput}) 5473 } 5474 5475 return itr 5476} 5477 5478// Stats returns an aggregation of stats from the underlying iterators. 5479func (itr *unsignedMergeIterator) Stats() IteratorStats { 5480 var stats IteratorStats 5481 for _, input := range itr.inputs { 5482 stats.Add(input.Stats()) 5483 } 5484 return stats 5485} 5486 5487// Close closes the underlying iterators. 5488func (itr *unsignedMergeIterator) Close() error { 5489 itr.mu.Lock() 5490 defer itr.mu.Unlock() 5491 5492 for _, input := range itr.inputs { 5493 input.Close() 5494 } 5495 itr.curr = nil 5496 itr.inputs = nil 5497 itr.heap.items = nil 5498 itr.closed = true 5499 return nil 5500} 5501 5502// Next returns the next point from the iterator. 5503func (itr *unsignedMergeIterator) Next() (*UnsignedPoint, error) { 5504 itr.mu.RLock() 5505 defer itr.mu.RUnlock() 5506 if itr.closed { 5507 return nil, nil 5508 } 5509 5510 // Initialize the heap. This needs to be done lazily on the first call to this iterator 5511 // so that iterator initialization done through the Select() call returns quickly. 5512 // Queries can only be interrupted after the Select() call completes so any operations 5513 // done during iterator creation cannot be interrupted, which is why we do it here 5514 // instead so an interrupt can happen while initializing the heap. 5515 if !itr.init { 5516 items := itr.heap.items 5517 itr.heap.items = make([]*unsignedMergeHeapItem, 0, len(items)) 5518 for _, item := range items { 5519 if p, err := item.itr.peek(); err != nil { 5520 return nil, err 5521 } else if p == nil { 5522 continue 5523 } 5524 itr.heap.items = append(itr.heap.items, item) 5525 } 5526 heap.Init(itr.heap) 5527 itr.init = true 5528 } 5529 5530 for { 5531 // Retrieve the next iterator if we don't have one. 5532 if itr.curr == nil { 5533 if len(itr.heap.items) == 0 { 5534 return nil, nil 5535 } 5536 itr.curr = heap.Pop(itr.heap).(*unsignedMergeHeapItem) 5537 5538 // Read point and set current window. 5539 p, err := itr.curr.itr.Next() 5540 if err != nil { 5541 return nil, err 5542 } 5543 tags := p.Tags.Subset(itr.heap.opt.Dimensions) 5544 itr.window.name, itr.window.tags = p.Name, tags.ID() 5545 itr.window.startTime, itr.window.endTime = itr.heap.opt.Window(p.Time) 5546 return p, nil 5547 } 5548 5549 // Read the next point from the current iterator. 5550 p, err := itr.curr.itr.Next() 5551 if err != nil { 5552 return nil, err 5553 } 5554 5555 // If there are no more points then remove iterator from heap and find next. 5556 if p == nil { 5557 itr.curr = nil 5558 continue 5559 } 5560 5561 // Check if the point is inside of our current window. 5562 inWindow := true 5563 if window := itr.window; window.name != p.Name { 5564 inWindow = false 5565 } else if tags := p.Tags.Subset(itr.heap.opt.Dimensions); window.tags != tags.ID() { 5566 inWindow = false 5567 } else if opt := itr.heap.opt; opt.Ascending && p.Time >= window.endTime { 5568 inWindow = false 5569 } else if !opt.Ascending && p.Time < window.startTime { 5570 inWindow = false 5571 } 5572 5573 // If it's outside our window then push iterator back on the heap and find new iterator. 5574 if !inWindow { 5575 itr.curr.itr.unread(p) 5576 heap.Push(itr.heap, itr.curr) 5577 itr.curr = nil 5578 continue 5579 } 5580 5581 return p, nil 5582 } 5583} 5584 5585// unsignedMergeHeap represents a heap of unsignedMergeHeapItems. 5586// Items are sorted by their next window and then by name/tags. 5587type unsignedMergeHeap struct { 5588 opt IteratorOptions 5589 items []*unsignedMergeHeapItem 5590} 5591 5592func (h *unsignedMergeHeap) Len() int { return len(h.items) } 5593func (h *unsignedMergeHeap) Swap(i, j int) { h.items[i], h.items[j] = h.items[j], h.items[i] } 5594func (h *unsignedMergeHeap) Less(i, j int) bool { 5595 x, err := h.items[i].itr.peek() 5596 if err != nil { 5597 return true 5598 } 5599 y, err := h.items[j].itr.peek() 5600 if err != nil { 5601 return false 5602 } 5603 5604 if h.opt.Ascending { 5605 if x.Name != y.Name { 5606 return x.Name < y.Name 5607 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); xTags.ID() != yTags.ID() { 5608 return xTags.ID() < yTags.ID() 5609 } 5610 } else { 5611 if x.Name != y.Name { 5612 return x.Name > y.Name 5613 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); xTags.ID() != yTags.ID() { 5614 return xTags.ID() > yTags.ID() 5615 } 5616 } 5617 5618 xt, _ := h.opt.Window(x.Time) 5619 yt, _ := h.opt.Window(y.Time) 5620 5621 if h.opt.Ascending { 5622 return xt < yt 5623 } 5624 return xt > yt 5625} 5626 5627func (h *unsignedMergeHeap) Push(x interface{}) { 5628 h.items = append(h.items, x.(*unsignedMergeHeapItem)) 5629} 5630 5631func (h *unsignedMergeHeap) Pop() interface{} { 5632 old := h.items 5633 n := len(old) 5634 item := old[n-1] 5635 h.items = old[0 : n-1] 5636 return item 5637} 5638 5639type unsignedMergeHeapItem struct { 5640 itr *bufUnsignedIterator 5641} 5642 5643// unsignedSortedMergeIterator is an iterator that sorts and merges multiple iterators into one. 5644type unsignedSortedMergeIterator struct { 5645 inputs []UnsignedIterator 5646 heap *unsignedSortedMergeHeap 5647 init bool 5648} 5649 5650// newUnsignedSortedMergeIterator returns an instance of unsignedSortedMergeIterator. 5651func newUnsignedSortedMergeIterator(inputs []UnsignedIterator, opt IteratorOptions) Iterator { 5652 itr := &unsignedSortedMergeIterator{ 5653 inputs: inputs, 5654 heap: &unsignedSortedMergeHeap{ 5655 items: make([]*unsignedSortedMergeHeapItem, 0, len(inputs)), 5656 opt: opt, 5657 }, 5658 } 5659 5660 // Initialize heap items. 5661 for _, input := range inputs { 5662 // Append to the heap. 5663 itr.heap.items = append(itr.heap.items, &unsignedSortedMergeHeapItem{itr: input}) 5664 } 5665 5666 return itr 5667} 5668 5669// Stats returns an aggregation of stats from the underlying iterators. 5670func (itr *unsignedSortedMergeIterator) Stats() IteratorStats { 5671 var stats IteratorStats 5672 for _, input := range itr.inputs { 5673 stats.Add(input.Stats()) 5674 } 5675 return stats 5676} 5677 5678// Close closes the underlying iterators. 5679func (itr *unsignedSortedMergeIterator) Close() error { 5680 for _, input := range itr.inputs { 5681 input.Close() 5682 } 5683 return nil 5684} 5685 5686// Next returns the next points from the iterator. 5687func (itr *unsignedSortedMergeIterator) Next() (*UnsignedPoint, error) { return itr.pop() } 5688 5689// pop returns the next point from the heap. 5690// Reads the next point from item's cursor and puts it back on the heap. 5691func (itr *unsignedSortedMergeIterator) pop() (*UnsignedPoint, error) { 5692 // Initialize the heap. See the MergeIterator to see why this has to be done lazily. 5693 if !itr.init { 5694 items := itr.heap.items 5695 itr.heap.items = make([]*unsignedSortedMergeHeapItem, 0, len(items)) 5696 for _, item := range items { 5697 var err error 5698 if item.point, err = item.itr.Next(); err != nil { 5699 return nil, err 5700 } else if item.point == nil { 5701 continue 5702 } 5703 itr.heap.items = append(itr.heap.items, item) 5704 } 5705 heap.Init(itr.heap) 5706 itr.init = true 5707 } 5708 5709 if len(itr.heap.items) == 0 { 5710 return nil, nil 5711 } 5712 5713 // Read the next item from the heap. 5714 item := heap.Pop(itr.heap).(*unsignedSortedMergeHeapItem) 5715 if item.err != nil { 5716 return nil, item.err 5717 } else if item.point == nil { 5718 return nil, nil 5719 } 5720 5721 // Copy the point for return. 5722 p := item.point.Clone() 5723 5724 // Read the next item from the cursor. Push back to heap if one exists. 5725 if item.point, item.err = item.itr.Next(); item.point != nil { 5726 heap.Push(itr.heap, item) 5727 } 5728 5729 return p, nil 5730} 5731 5732// unsignedSortedMergeHeap represents a heap of unsignedSortedMergeHeapItems. 5733// Items are sorted with the following priority: 5734// - By their measurement name; 5735// - By their tag keys/values; 5736// - By time; or 5737// - By their Aux field values. 5738// 5739type unsignedSortedMergeHeap struct { 5740 opt IteratorOptions 5741 items []*unsignedSortedMergeHeapItem 5742} 5743 5744func (h *unsignedSortedMergeHeap) Len() int { return len(h.items) } 5745func (h *unsignedSortedMergeHeap) Swap(i, j int) { h.items[i], h.items[j] = h.items[j], h.items[i] } 5746func (h *unsignedSortedMergeHeap) Less(i, j int) bool { 5747 x, y := h.items[i].point, h.items[j].point 5748 5749 if h.opt.Ascending { 5750 if x.Name != y.Name { 5751 return x.Name < y.Name 5752 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); !xTags.Equals(&yTags) { 5753 return xTags.ID() < yTags.ID() 5754 } 5755 5756 if x.Time != y.Time { 5757 return x.Time < y.Time 5758 } 5759 5760 if len(x.Aux) > 0 && len(x.Aux) == len(y.Aux) { 5761 for i := 0; i < len(x.Aux); i++ { 5762 v1, ok1 := x.Aux[i].(string) 5763 v2, ok2 := y.Aux[i].(string) 5764 if !ok1 || !ok2 { 5765 // Unsupported types used in Aux fields. Maybe they 5766 // need to be added here? 5767 return false 5768 } else if v1 == v2 { 5769 continue 5770 } 5771 return v1 < v2 5772 } 5773 } 5774 return false // Times and/or Aux fields are equal. 5775 } 5776 5777 if x.Name != y.Name { 5778 return x.Name > y.Name 5779 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); !xTags.Equals(&yTags) { 5780 return xTags.ID() > yTags.ID() 5781 } 5782 5783 if x.Time != y.Time { 5784 return x.Time > y.Time 5785 } 5786 5787 if len(x.Aux) > 0 && len(x.Aux) == len(y.Aux) { 5788 for i := 0; i < len(x.Aux); i++ { 5789 v1, ok1 := x.Aux[i].(string) 5790 v2, ok2 := y.Aux[i].(string) 5791 if !ok1 || !ok2 { 5792 // Unsupported types used in Aux fields. Maybe they 5793 // need to be added here? 5794 return false 5795 } else if v1 == v2 { 5796 continue 5797 } 5798 return v1 > v2 5799 } 5800 } 5801 return false // Times and/or Aux fields are equal. 5802} 5803 5804func (h *unsignedSortedMergeHeap) Push(x interface{}) { 5805 h.items = append(h.items, x.(*unsignedSortedMergeHeapItem)) 5806} 5807 5808func (h *unsignedSortedMergeHeap) Pop() interface{} { 5809 old := h.items 5810 n := len(old) 5811 item := old[n-1] 5812 h.items = old[0 : n-1] 5813 return item 5814} 5815 5816type unsignedSortedMergeHeapItem struct { 5817 point *UnsignedPoint 5818 err error 5819 itr UnsignedIterator 5820} 5821 5822// unsignedIteratorScanner scans the results of a UnsignedIterator into a map. 5823type unsignedIteratorScanner struct { 5824 input *bufUnsignedIterator 5825 err error 5826 keys []influxql.VarRef 5827 defaultValue interface{} 5828} 5829 5830// newUnsignedIteratorScanner creates a new IteratorScanner. 5831func newUnsignedIteratorScanner(input UnsignedIterator, keys []influxql.VarRef, defaultValue interface{}) *unsignedIteratorScanner { 5832 return &unsignedIteratorScanner{ 5833 input: newBufUnsignedIterator(input), 5834 keys: keys, 5835 defaultValue: defaultValue, 5836 } 5837} 5838 5839func (s *unsignedIteratorScanner) Peek() (int64, string, Tags) { 5840 if s.err != nil { 5841 return ZeroTime, "", Tags{} 5842 } 5843 5844 p, err := s.input.peek() 5845 if err != nil { 5846 s.err = err 5847 return ZeroTime, "", Tags{} 5848 } else if p == nil { 5849 return ZeroTime, "", Tags{} 5850 } 5851 return p.Time, p.Name, p.Tags 5852} 5853 5854func (s *unsignedIteratorScanner) ScanAt(ts int64, name string, tags Tags, m map[string]interface{}) { 5855 if s.err != nil { 5856 return 5857 } 5858 5859 p, err := s.input.Next() 5860 if err != nil { 5861 s.err = err 5862 return 5863 } else if p == nil { 5864 s.useDefaults(m) 5865 return 5866 } else if p.Time != ts || p.Name != name || !p.Tags.Equals(&tags) { 5867 s.useDefaults(m) 5868 s.input.unread(p) 5869 return 5870 } 5871 5872 if k := s.keys[0]; k.Val != "" { 5873 if p.Nil { 5874 if s.defaultValue != SkipDefault { 5875 m[k.Val] = castToType(s.defaultValue, k.Type) 5876 } 5877 } else { 5878 m[k.Val] = p.Value 5879 } 5880 } 5881 for i, v := range p.Aux { 5882 k := s.keys[i+1] 5883 switch v.(type) { 5884 case float64, int64, uint64, string, bool: 5885 m[k.Val] = v 5886 default: 5887 // Insert the fill value if one was specified. 5888 if s.defaultValue != SkipDefault { 5889 m[k.Val] = castToType(s.defaultValue, k.Type) 5890 } 5891 } 5892 } 5893} 5894 5895func (s *unsignedIteratorScanner) useDefaults(m map[string]interface{}) { 5896 if s.defaultValue == SkipDefault { 5897 return 5898 } 5899 for _, k := range s.keys { 5900 if k.Val == "" { 5901 continue 5902 } 5903 m[k.Val] = castToType(s.defaultValue, k.Type) 5904 } 5905} 5906 5907func (s *unsignedIteratorScanner) Stats() IteratorStats { return s.input.Stats() } 5908func (s *unsignedIteratorScanner) Err() error { return s.err } 5909func (s *unsignedIteratorScanner) Close() error { return s.input.Close() } 5910 5911// unsignedParallelIterator represents an iterator that pulls data in a separate goroutine. 5912type unsignedParallelIterator struct { 5913 input UnsignedIterator 5914 ch chan unsignedPointError 5915 5916 once sync.Once 5917 closing chan struct{} 5918 wg sync.WaitGroup 5919} 5920 5921// newUnsignedParallelIterator returns a new instance of unsignedParallelIterator. 5922func newUnsignedParallelIterator(input UnsignedIterator) *unsignedParallelIterator { 5923 itr := &unsignedParallelIterator{ 5924 input: input, 5925 ch: make(chan unsignedPointError, 256), 5926 closing: make(chan struct{}), 5927 } 5928 itr.wg.Add(1) 5929 go itr.monitor() 5930 return itr 5931} 5932 5933// Stats returns stats from the underlying iterator. 5934func (itr *unsignedParallelIterator) Stats() IteratorStats { return itr.input.Stats() } 5935 5936// Close closes the underlying iterators. 5937func (itr *unsignedParallelIterator) Close() error { 5938 itr.once.Do(func() { close(itr.closing) }) 5939 itr.wg.Wait() 5940 return itr.input.Close() 5941} 5942 5943// Next returns the next point from the iterator. 5944func (itr *unsignedParallelIterator) Next() (*UnsignedPoint, error) { 5945 v, ok := <-itr.ch 5946 if !ok { 5947 return nil, io.EOF 5948 } 5949 return v.point, v.err 5950} 5951 5952// monitor runs in a separate goroutine and actively pulls the next point. 5953func (itr *unsignedParallelIterator) monitor() { 5954 defer close(itr.ch) 5955 defer itr.wg.Done() 5956 5957 for { 5958 // Read next point. 5959 p, err := itr.input.Next() 5960 if p != nil { 5961 p = p.Clone() 5962 } 5963 5964 select { 5965 case <-itr.closing: 5966 return 5967 case itr.ch <- unsignedPointError{point: p, err: err}: 5968 } 5969 } 5970} 5971 5972type unsignedPointError struct { 5973 point *UnsignedPoint 5974 err error 5975} 5976 5977// unsignedLimitIterator represents an iterator that limits points per group. 5978type unsignedLimitIterator struct { 5979 input UnsignedIterator 5980 opt IteratorOptions 5981 n int 5982 5983 prev struct { 5984 name string 5985 tags Tags 5986 } 5987} 5988 5989// newUnsignedLimitIterator returns a new instance of unsignedLimitIterator. 5990func newUnsignedLimitIterator(input UnsignedIterator, opt IteratorOptions) *unsignedLimitIterator { 5991 return &unsignedLimitIterator{ 5992 input: input, 5993 opt: opt, 5994 } 5995} 5996 5997// Stats returns stats from the underlying iterator. 5998func (itr *unsignedLimitIterator) Stats() IteratorStats { return itr.input.Stats() } 5999 6000// Close closes the underlying iterators. 6001func (itr *unsignedLimitIterator) Close() error { return itr.input.Close() } 6002 6003// Next returns the next point from the iterator. 6004func (itr *unsignedLimitIterator) Next() (*UnsignedPoint, error) { 6005 for { 6006 p, err := itr.input.Next() 6007 if p == nil || err != nil { 6008 return nil, err 6009 } 6010 6011 // Reset window and counter if a new window is encountered. 6012 if p.Name != itr.prev.name || !p.Tags.Equals(&itr.prev.tags) { 6013 itr.prev.name = p.Name 6014 itr.prev.tags = p.Tags 6015 itr.n = 0 6016 } 6017 6018 // Increment counter. 6019 itr.n++ 6020 6021 // Read next point if not beyond the offset. 6022 if itr.n <= itr.opt.Offset { 6023 continue 6024 } 6025 6026 // Read next point if we're beyond the limit. 6027 if itr.opt.Limit > 0 && (itr.n-itr.opt.Offset) > itr.opt.Limit { 6028 continue 6029 } 6030 6031 return p, nil 6032 } 6033} 6034 6035type unsignedFillIterator struct { 6036 input *bufUnsignedIterator 6037 prev UnsignedPoint 6038 startTime int64 6039 endTime int64 6040 auxFields []interface{} 6041 init bool 6042 opt IteratorOptions 6043 6044 window struct { 6045 name string 6046 tags Tags 6047 time int64 6048 offset int64 6049 } 6050} 6051 6052func newUnsignedFillIterator(input UnsignedIterator, expr influxql.Expr, opt IteratorOptions) *unsignedFillIterator { 6053 if opt.Fill == influxql.NullFill { 6054 if expr, ok := expr.(*influxql.Call); ok && expr.Name == "count" { 6055 opt.Fill = influxql.NumberFill 6056 opt.FillValue = uint64(0) 6057 } 6058 } 6059 6060 var startTime, endTime int64 6061 if opt.Ascending { 6062 startTime, _ = opt.Window(opt.StartTime) 6063 endTime, _ = opt.Window(opt.EndTime) 6064 } else { 6065 startTime, _ = opt.Window(opt.EndTime) 6066 endTime, _ = opt.Window(opt.StartTime) 6067 } 6068 6069 var auxFields []interface{} 6070 if len(opt.Aux) > 0 { 6071 auxFields = make([]interface{}, len(opt.Aux)) 6072 } 6073 6074 return &unsignedFillIterator{ 6075 input: newBufUnsignedIterator(input), 6076 prev: UnsignedPoint{Nil: true}, 6077 startTime: startTime, 6078 endTime: endTime, 6079 auxFields: auxFields, 6080 opt: opt, 6081 } 6082} 6083 6084func (itr *unsignedFillIterator) Stats() IteratorStats { return itr.input.Stats() } 6085func (itr *unsignedFillIterator) Close() error { return itr.input.Close() } 6086 6087func (itr *unsignedFillIterator) Next() (*UnsignedPoint, error) { 6088 if !itr.init { 6089 p, err := itr.input.peek() 6090 if p == nil || err != nil { 6091 return nil, err 6092 } 6093 itr.window.name, itr.window.tags = p.Name, p.Tags 6094 itr.window.time = itr.startTime 6095 if itr.startTime == influxql.MinTime { 6096 itr.window.time, _ = itr.opt.Window(p.Time) 6097 } 6098 if itr.opt.Location != nil { 6099 _, itr.window.offset = itr.opt.Zone(itr.window.time) 6100 } 6101 itr.init = true 6102 } 6103 6104 p, err := itr.input.Next() 6105 if err != nil { 6106 return nil, err 6107 } 6108 6109 // Check if the next point is outside of our window or is nil. 6110 if p == nil || p.Name != itr.window.name || p.Tags.ID() != itr.window.tags.ID() { 6111 // If we are inside of an interval, unread the point and continue below to 6112 // constructing a new point. 6113 if itr.opt.Ascending && itr.window.time <= itr.endTime { 6114 itr.input.unread(p) 6115 p = nil 6116 goto CONSTRUCT 6117 } else if !itr.opt.Ascending && itr.window.time >= itr.endTime && itr.endTime != influxql.MinTime { 6118 itr.input.unread(p) 6119 p = nil 6120 goto CONSTRUCT 6121 } 6122 6123 // We are *not* in a current interval. If there is no next point, 6124 // we are at the end of all intervals. 6125 if p == nil { 6126 return nil, nil 6127 } 6128 6129 // Set the new interval. 6130 itr.window.name, itr.window.tags = p.Name, p.Tags 6131 itr.window.time = itr.startTime 6132 if itr.window.time == influxql.MinTime { 6133 itr.window.time, _ = itr.opt.Window(p.Time) 6134 } 6135 if itr.opt.Location != nil { 6136 _, itr.window.offset = itr.opt.Zone(itr.window.time) 6137 } 6138 itr.prev = UnsignedPoint{Nil: true} 6139 } 6140 6141 // Check if the point is our next expected point. 6142CONSTRUCT: 6143 if p == nil || (itr.opt.Ascending && p.Time > itr.window.time) || (!itr.opt.Ascending && p.Time < itr.window.time) { 6144 if p != nil { 6145 itr.input.unread(p) 6146 } 6147 6148 p = &UnsignedPoint{ 6149 Name: itr.window.name, 6150 Tags: itr.window.tags, 6151 Time: itr.window.time, 6152 Aux: itr.auxFields, 6153 } 6154 6155 switch itr.opt.Fill { 6156 case influxql.LinearFill: 6157 if !itr.prev.Nil { 6158 next, err := itr.input.peek() 6159 if err != nil { 6160 return nil, err 6161 } else if next != nil && next.Name == itr.window.name && next.Tags.ID() == itr.window.tags.ID() { 6162 interval := int64(itr.opt.Interval.Duration) 6163 start := itr.window.time / interval 6164 p.Value = linearUnsigned(start, itr.prev.Time/interval, next.Time/interval, itr.prev.Value, next.Value) 6165 } else { 6166 p.Nil = true 6167 } 6168 } else { 6169 p.Nil = true 6170 } 6171 6172 case influxql.NullFill: 6173 p.Nil = true 6174 case influxql.NumberFill: 6175 p.Value, _ = castToUnsigned(itr.opt.FillValue) 6176 case influxql.PreviousFill: 6177 if !itr.prev.Nil { 6178 p.Value = itr.prev.Value 6179 p.Nil = itr.prev.Nil 6180 } else { 6181 p.Nil = true 6182 } 6183 } 6184 } else { 6185 itr.prev = *p 6186 } 6187 6188 // Advance the expected time. Do not advance to a new window here 6189 // as there may be lingering points with the same timestamp in the previous 6190 // window. 6191 if itr.opt.Ascending { 6192 itr.window.time += int64(itr.opt.Interval.Duration) 6193 } else { 6194 itr.window.time -= int64(itr.opt.Interval.Duration) 6195 } 6196 6197 // Check to see if we have passed over an offset change and adjust the time 6198 // to account for this new offset. 6199 if itr.opt.Location != nil { 6200 if _, offset := itr.opt.Zone(itr.window.time - 1); offset != itr.window.offset { 6201 diff := itr.window.offset - offset 6202 if abs(diff) < int64(itr.opt.Interval.Duration) { 6203 itr.window.time += diff 6204 } 6205 itr.window.offset = offset 6206 } 6207 } 6208 return p, nil 6209} 6210 6211// unsignedIntervalIterator represents a unsigned implementation of IntervalIterator. 6212type unsignedIntervalIterator struct { 6213 input UnsignedIterator 6214 opt IteratorOptions 6215} 6216 6217func newUnsignedIntervalIterator(input UnsignedIterator, opt IteratorOptions) *unsignedIntervalIterator { 6218 return &unsignedIntervalIterator{input: input, opt: opt} 6219} 6220 6221func (itr *unsignedIntervalIterator) Stats() IteratorStats { return itr.input.Stats() } 6222func (itr *unsignedIntervalIterator) Close() error { return itr.input.Close() } 6223 6224func (itr *unsignedIntervalIterator) Next() (*UnsignedPoint, error) { 6225 p, err := itr.input.Next() 6226 if p == nil || err != nil { 6227 return nil, err 6228 } 6229 p.Time, _ = itr.opt.Window(p.Time) 6230 // If we see the minimum allowable time, set the time to zero so we don't 6231 // break the default returned time for aggregate queries without times. 6232 if p.Time == influxql.MinTime { 6233 p.Time = 0 6234 } 6235 return p, nil 6236} 6237 6238// unsignedInterruptIterator represents a unsigned implementation of InterruptIterator. 6239type unsignedInterruptIterator struct { 6240 input UnsignedIterator 6241 closing <-chan struct{} 6242 count int 6243} 6244 6245func newUnsignedInterruptIterator(input UnsignedIterator, closing <-chan struct{}) *unsignedInterruptIterator { 6246 return &unsignedInterruptIterator{input: input, closing: closing} 6247} 6248 6249func (itr *unsignedInterruptIterator) Stats() IteratorStats { return itr.input.Stats() } 6250func (itr *unsignedInterruptIterator) Close() error { return itr.input.Close() } 6251 6252func (itr *unsignedInterruptIterator) Next() (*UnsignedPoint, error) { 6253 // Only check if the channel is closed every N points. This 6254 // intentionally checks on both 0 and N so that if the iterator 6255 // has been interrupted before the first point is emitted it will 6256 // not emit any points. 6257 if itr.count&0xFF == 0xFF { 6258 select { 6259 case <-itr.closing: 6260 return nil, itr.Close() 6261 default: 6262 // Reset iterator count to zero and fall through to emit the next point. 6263 itr.count = 0 6264 } 6265 } 6266 6267 // Increment the counter for every point read. 6268 itr.count++ 6269 return itr.input.Next() 6270} 6271 6272// unsignedCloseInterruptIterator represents a unsigned implementation of CloseInterruptIterator. 6273type unsignedCloseInterruptIterator struct { 6274 input UnsignedIterator 6275 closing <-chan struct{} 6276 done chan struct{} 6277 once sync.Once 6278} 6279 6280func newUnsignedCloseInterruptIterator(input UnsignedIterator, closing <-chan struct{}) *unsignedCloseInterruptIterator { 6281 itr := &unsignedCloseInterruptIterator{ 6282 input: input, 6283 closing: closing, 6284 done: make(chan struct{}), 6285 } 6286 go itr.monitor() 6287 return itr 6288} 6289 6290func (itr *unsignedCloseInterruptIterator) monitor() { 6291 select { 6292 case <-itr.closing: 6293 itr.Close() 6294 case <-itr.done: 6295 } 6296} 6297 6298func (itr *unsignedCloseInterruptIterator) Stats() IteratorStats { 6299 return itr.input.Stats() 6300} 6301 6302func (itr *unsignedCloseInterruptIterator) Close() error { 6303 itr.once.Do(func() { 6304 close(itr.done) 6305 itr.input.Close() 6306 }) 6307 return nil 6308} 6309 6310func (itr *unsignedCloseInterruptIterator) Next() (*UnsignedPoint, error) { 6311 p, err := itr.input.Next() 6312 if err != nil { 6313 // Check if the iterator was closed. 6314 select { 6315 case <-itr.done: 6316 return nil, nil 6317 default: 6318 return nil, err 6319 } 6320 } 6321 return p, nil 6322} 6323 6324// unsignedReduceFloatIterator executes a reducer for every interval and buffers the result. 6325type unsignedReduceFloatIterator struct { 6326 input *bufUnsignedIterator 6327 create func() (UnsignedPointAggregator, FloatPointEmitter) 6328 dims []string 6329 opt IteratorOptions 6330 points []FloatPoint 6331 keepTags bool 6332} 6333 6334func newUnsignedReduceFloatIterator(input UnsignedIterator, opt IteratorOptions, createFn func() (UnsignedPointAggregator, FloatPointEmitter)) *unsignedReduceFloatIterator { 6335 return &unsignedReduceFloatIterator{ 6336 input: newBufUnsignedIterator(input), 6337 create: createFn, 6338 dims: opt.GetDimensions(), 6339 opt: opt, 6340 } 6341} 6342 6343// Stats returns stats from the input iterator. 6344func (itr *unsignedReduceFloatIterator) Stats() IteratorStats { return itr.input.Stats() } 6345 6346// Close closes the iterator and all child iterators. 6347func (itr *unsignedReduceFloatIterator) Close() error { return itr.input.Close() } 6348 6349// Next returns the minimum value for the next available interval. 6350func (itr *unsignedReduceFloatIterator) Next() (*FloatPoint, error) { 6351 // Calculate next window if we have no more points. 6352 if len(itr.points) == 0 { 6353 var err error 6354 itr.points, err = itr.reduce() 6355 if len(itr.points) == 0 { 6356 return nil, err 6357 } 6358 } 6359 6360 // Pop next point off the stack. 6361 p := &itr.points[len(itr.points)-1] 6362 itr.points = itr.points[:len(itr.points)-1] 6363 return p, nil 6364} 6365 6366// unsignedReduceFloatPoint stores the reduced data for a name/tag combination. 6367type unsignedReduceFloatPoint struct { 6368 Name string 6369 Tags Tags 6370 Aggregator UnsignedPointAggregator 6371 Emitter FloatPointEmitter 6372} 6373 6374// reduce executes fn once for every point in the next window. 6375// The previous value for the dimension is passed to fn. 6376func (itr *unsignedReduceFloatIterator) reduce() ([]FloatPoint, error) { 6377 // Calculate next window. 6378 var ( 6379 startTime, endTime int64 6380 window struct { 6381 name string 6382 tags string 6383 } 6384 ) 6385 for { 6386 p, err := itr.input.Next() 6387 if err != nil || p == nil { 6388 return nil, err 6389 } else if p.Nil { 6390 continue 6391 } 6392 6393 // Unread the point so it can be processed. 6394 itr.input.unread(p) 6395 startTime, endTime = itr.opt.Window(p.Time) 6396 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 6397 break 6398 } 6399 6400 // Create points by tags. 6401 m := make(map[string]*unsignedReduceFloatPoint) 6402 for { 6403 // Read next point. 6404 curr, err := itr.input.NextInWindow(startTime, endTime) 6405 if err != nil { 6406 return nil, err 6407 } else if curr == nil { 6408 break 6409 } else if curr.Nil { 6410 continue 6411 } else if curr.Name != window.name { 6412 itr.input.unread(curr) 6413 break 6414 } 6415 6416 // Ensure this point is within the same final window. 6417 if curr.Name != window.name { 6418 itr.input.unread(curr) 6419 break 6420 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 6421 itr.input.unread(curr) 6422 break 6423 } 6424 6425 // Retrieve the tags on this point for this level of the query. 6426 // This may be different than the bucket dimensions. 6427 tags := curr.Tags.Subset(itr.dims) 6428 id := tags.ID() 6429 6430 // Retrieve the aggregator for this name/tag combination or create one. 6431 rp := m[id] 6432 if rp == nil { 6433 aggregator, emitter := itr.create() 6434 rp = &unsignedReduceFloatPoint{ 6435 Name: curr.Name, 6436 Tags: tags, 6437 Aggregator: aggregator, 6438 Emitter: emitter, 6439 } 6440 m[id] = rp 6441 } 6442 rp.Aggregator.AggregateUnsigned(curr) 6443 } 6444 6445 keys := make([]string, 0, len(m)) 6446 for k := range m { 6447 keys = append(keys, k) 6448 } 6449 6450 // Reverse sort points by name & tag. 6451 // This ensures a consistent order of output. 6452 if len(keys) > 0 { 6453 var sorted sort.Interface = sort.StringSlice(keys) 6454 if itr.opt.Ascending { 6455 sorted = sort.Reverse(sorted) 6456 } 6457 sort.Sort(sorted) 6458 } 6459 6460 // Assume the points are already sorted until proven otherwise. 6461 sortedByTime := true 6462 // Emit the points for each name & tag combination. 6463 a := make([]FloatPoint, 0, len(m)) 6464 for _, k := range keys { 6465 rp := m[k] 6466 points := rp.Emitter.Emit() 6467 for i := len(points) - 1; i >= 0; i-- { 6468 points[i].Name = rp.Name 6469 if !itr.keepTags { 6470 points[i].Tags = rp.Tags 6471 } 6472 // Set the points time to the interval time if the reducer didn't provide one. 6473 if points[i].Time == ZeroTime { 6474 points[i].Time = startTime 6475 } else { 6476 sortedByTime = false 6477 } 6478 a = append(a, points[i]) 6479 } 6480 } 6481 // Points may be out of order. Perform a stable sort by time if requested. 6482 if !sortedByTime && itr.opt.Ordered { 6483 var sorted sort.Interface = floatPointsByTime(a) 6484 if itr.opt.Ascending { 6485 sorted = sort.Reverse(sorted) 6486 } 6487 sort.Stable(sorted) 6488 } 6489 return a, nil 6490} 6491 6492// unsignedStreamFloatIterator streams inputs into the iterator and emits points gradually. 6493type unsignedStreamFloatIterator struct { 6494 input *bufUnsignedIterator 6495 create func() (UnsignedPointAggregator, FloatPointEmitter) 6496 dims []string 6497 opt IteratorOptions 6498 m map[string]*unsignedReduceFloatPoint 6499 points []FloatPoint 6500} 6501 6502// newUnsignedStreamFloatIterator returns a new instance of unsignedStreamFloatIterator. 6503func newUnsignedStreamFloatIterator(input UnsignedIterator, createFn func() (UnsignedPointAggregator, FloatPointEmitter), opt IteratorOptions) *unsignedStreamFloatIterator { 6504 return &unsignedStreamFloatIterator{ 6505 input: newBufUnsignedIterator(input), 6506 create: createFn, 6507 dims: opt.GetDimensions(), 6508 opt: opt, 6509 m: make(map[string]*unsignedReduceFloatPoint), 6510 } 6511} 6512 6513// Stats returns stats from the input iterator. 6514func (itr *unsignedStreamFloatIterator) Stats() IteratorStats { return itr.input.Stats() } 6515 6516// Close closes the iterator and all child iterators. 6517func (itr *unsignedStreamFloatIterator) Close() error { return itr.input.Close() } 6518 6519// Next returns the next value for the stream iterator. 6520func (itr *unsignedStreamFloatIterator) Next() (*FloatPoint, error) { 6521 // Calculate next window if we have no more points. 6522 if len(itr.points) == 0 { 6523 var err error 6524 itr.points, err = itr.reduce() 6525 if len(itr.points) == 0 { 6526 return nil, err 6527 } 6528 } 6529 6530 // Pop next point off the stack. 6531 p := &itr.points[len(itr.points)-1] 6532 itr.points = itr.points[:len(itr.points)-1] 6533 return p, nil 6534} 6535 6536// reduce creates and manages aggregators for every point from the input. 6537// After aggregating a point, it always tries to emit a value using the emitter. 6538func (itr *unsignedStreamFloatIterator) reduce() ([]FloatPoint, error) { 6539 // We have already read all of the input points. 6540 if itr.m == nil { 6541 return nil, nil 6542 } 6543 6544 for { 6545 // Read next point. 6546 curr, err := itr.input.Next() 6547 if err != nil { 6548 return nil, err 6549 } else if curr == nil { 6550 // Close all of the aggregators to flush any remaining points to emit. 6551 var points []FloatPoint 6552 for _, rp := range itr.m { 6553 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 6554 if err := aggregator.Close(); err != nil { 6555 return nil, err 6556 } 6557 6558 pts := rp.Emitter.Emit() 6559 if len(pts) == 0 { 6560 continue 6561 } 6562 6563 for i := range pts { 6564 pts[i].Name = rp.Name 6565 pts[i].Tags = rp.Tags 6566 } 6567 points = append(points, pts...) 6568 } 6569 } 6570 6571 // Eliminate the aggregators and emitters. 6572 itr.m = nil 6573 return points, nil 6574 } else if curr.Nil { 6575 continue 6576 } 6577 tags := curr.Tags.Subset(itr.dims) 6578 6579 id := curr.Name 6580 if len(tags.m) > 0 { 6581 id += "\x00" + tags.ID() 6582 } 6583 6584 // Retrieve the aggregator for this name/tag combination or create one. 6585 rp := itr.m[id] 6586 if rp == nil { 6587 aggregator, emitter := itr.create() 6588 rp = &unsignedReduceFloatPoint{ 6589 Name: curr.Name, 6590 Tags: tags, 6591 Aggregator: aggregator, 6592 Emitter: emitter, 6593 } 6594 itr.m[id] = rp 6595 } 6596 rp.Aggregator.AggregateUnsigned(curr) 6597 6598 // Attempt to emit points from the aggregator. 6599 points := rp.Emitter.Emit() 6600 if len(points) == 0 { 6601 continue 6602 } 6603 6604 for i := range points { 6605 points[i].Name = rp.Name 6606 points[i].Tags = rp.Tags 6607 } 6608 return points, nil 6609 } 6610} 6611 6612// unsignedReduceIntegerIterator executes a reducer for every interval and buffers the result. 6613type unsignedReduceIntegerIterator struct { 6614 input *bufUnsignedIterator 6615 create func() (UnsignedPointAggregator, IntegerPointEmitter) 6616 dims []string 6617 opt IteratorOptions 6618 points []IntegerPoint 6619 keepTags bool 6620} 6621 6622func newUnsignedReduceIntegerIterator(input UnsignedIterator, opt IteratorOptions, createFn func() (UnsignedPointAggregator, IntegerPointEmitter)) *unsignedReduceIntegerIterator { 6623 return &unsignedReduceIntegerIterator{ 6624 input: newBufUnsignedIterator(input), 6625 create: createFn, 6626 dims: opt.GetDimensions(), 6627 opt: opt, 6628 } 6629} 6630 6631// Stats returns stats from the input iterator. 6632func (itr *unsignedReduceIntegerIterator) Stats() IteratorStats { return itr.input.Stats() } 6633 6634// Close closes the iterator and all child iterators. 6635func (itr *unsignedReduceIntegerIterator) Close() error { return itr.input.Close() } 6636 6637// Next returns the minimum value for the next available interval. 6638func (itr *unsignedReduceIntegerIterator) Next() (*IntegerPoint, error) { 6639 // Calculate next window if we have no more points. 6640 if len(itr.points) == 0 { 6641 var err error 6642 itr.points, err = itr.reduce() 6643 if len(itr.points) == 0 { 6644 return nil, err 6645 } 6646 } 6647 6648 // Pop next point off the stack. 6649 p := &itr.points[len(itr.points)-1] 6650 itr.points = itr.points[:len(itr.points)-1] 6651 return p, nil 6652} 6653 6654// unsignedReduceIntegerPoint stores the reduced data for a name/tag combination. 6655type unsignedReduceIntegerPoint struct { 6656 Name string 6657 Tags Tags 6658 Aggregator UnsignedPointAggregator 6659 Emitter IntegerPointEmitter 6660} 6661 6662// reduce executes fn once for every point in the next window. 6663// The previous value for the dimension is passed to fn. 6664func (itr *unsignedReduceIntegerIterator) reduce() ([]IntegerPoint, error) { 6665 // Calculate next window. 6666 var ( 6667 startTime, endTime int64 6668 window struct { 6669 name string 6670 tags string 6671 } 6672 ) 6673 for { 6674 p, err := itr.input.Next() 6675 if err != nil || p == nil { 6676 return nil, err 6677 } else if p.Nil { 6678 continue 6679 } 6680 6681 // Unread the point so it can be processed. 6682 itr.input.unread(p) 6683 startTime, endTime = itr.opt.Window(p.Time) 6684 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 6685 break 6686 } 6687 6688 // Create points by tags. 6689 m := make(map[string]*unsignedReduceIntegerPoint) 6690 for { 6691 // Read next point. 6692 curr, err := itr.input.NextInWindow(startTime, endTime) 6693 if err != nil { 6694 return nil, err 6695 } else if curr == nil { 6696 break 6697 } else if curr.Nil { 6698 continue 6699 } else if curr.Name != window.name { 6700 itr.input.unread(curr) 6701 break 6702 } 6703 6704 // Ensure this point is within the same final window. 6705 if curr.Name != window.name { 6706 itr.input.unread(curr) 6707 break 6708 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 6709 itr.input.unread(curr) 6710 break 6711 } 6712 6713 // Retrieve the tags on this point for this level of the query. 6714 // This may be different than the bucket dimensions. 6715 tags := curr.Tags.Subset(itr.dims) 6716 id := tags.ID() 6717 6718 // Retrieve the aggregator for this name/tag combination or create one. 6719 rp := m[id] 6720 if rp == nil { 6721 aggregator, emitter := itr.create() 6722 rp = &unsignedReduceIntegerPoint{ 6723 Name: curr.Name, 6724 Tags: tags, 6725 Aggregator: aggregator, 6726 Emitter: emitter, 6727 } 6728 m[id] = rp 6729 } 6730 rp.Aggregator.AggregateUnsigned(curr) 6731 } 6732 6733 keys := make([]string, 0, len(m)) 6734 for k := range m { 6735 keys = append(keys, k) 6736 } 6737 6738 // Reverse sort points by name & tag. 6739 // This ensures a consistent order of output. 6740 if len(keys) > 0 { 6741 var sorted sort.Interface = sort.StringSlice(keys) 6742 if itr.opt.Ascending { 6743 sorted = sort.Reverse(sorted) 6744 } 6745 sort.Sort(sorted) 6746 } 6747 6748 // Assume the points are already sorted until proven otherwise. 6749 sortedByTime := true 6750 // Emit the points for each name & tag combination. 6751 a := make([]IntegerPoint, 0, len(m)) 6752 for _, k := range keys { 6753 rp := m[k] 6754 points := rp.Emitter.Emit() 6755 for i := len(points) - 1; i >= 0; i-- { 6756 points[i].Name = rp.Name 6757 if !itr.keepTags { 6758 points[i].Tags = rp.Tags 6759 } 6760 // Set the points time to the interval time if the reducer didn't provide one. 6761 if points[i].Time == ZeroTime { 6762 points[i].Time = startTime 6763 } else { 6764 sortedByTime = false 6765 } 6766 a = append(a, points[i]) 6767 } 6768 } 6769 // Points may be out of order. Perform a stable sort by time if requested. 6770 if !sortedByTime && itr.opt.Ordered { 6771 var sorted sort.Interface = integerPointsByTime(a) 6772 if itr.opt.Ascending { 6773 sorted = sort.Reverse(sorted) 6774 } 6775 sort.Stable(sorted) 6776 } 6777 return a, nil 6778} 6779 6780// unsignedStreamIntegerIterator streams inputs into the iterator and emits points gradually. 6781type unsignedStreamIntegerIterator struct { 6782 input *bufUnsignedIterator 6783 create func() (UnsignedPointAggregator, IntegerPointEmitter) 6784 dims []string 6785 opt IteratorOptions 6786 m map[string]*unsignedReduceIntegerPoint 6787 points []IntegerPoint 6788} 6789 6790// newUnsignedStreamIntegerIterator returns a new instance of unsignedStreamIntegerIterator. 6791func newUnsignedStreamIntegerIterator(input UnsignedIterator, createFn func() (UnsignedPointAggregator, IntegerPointEmitter), opt IteratorOptions) *unsignedStreamIntegerIterator { 6792 return &unsignedStreamIntegerIterator{ 6793 input: newBufUnsignedIterator(input), 6794 create: createFn, 6795 dims: opt.GetDimensions(), 6796 opt: opt, 6797 m: make(map[string]*unsignedReduceIntegerPoint), 6798 } 6799} 6800 6801// Stats returns stats from the input iterator. 6802func (itr *unsignedStreamIntegerIterator) Stats() IteratorStats { return itr.input.Stats() } 6803 6804// Close closes the iterator and all child iterators. 6805func (itr *unsignedStreamIntegerIterator) Close() error { return itr.input.Close() } 6806 6807// Next returns the next value for the stream iterator. 6808func (itr *unsignedStreamIntegerIterator) Next() (*IntegerPoint, error) { 6809 // Calculate next window if we have no more points. 6810 if len(itr.points) == 0 { 6811 var err error 6812 itr.points, err = itr.reduce() 6813 if len(itr.points) == 0 { 6814 return nil, err 6815 } 6816 } 6817 6818 // Pop next point off the stack. 6819 p := &itr.points[len(itr.points)-1] 6820 itr.points = itr.points[:len(itr.points)-1] 6821 return p, nil 6822} 6823 6824// reduce creates and manages aggregators for every point from the input. 6825// After aggregating a point, it always tries to emit a value using the emitter. 6826func (itr *unsignedStreamIntegerIterator) reduce() ([]IntegerPoint, error) { 6827 // We have already read all of the input points. 6828 if itr.m == nil { 6829 return nil, nil 6830 } 6831 6832 for { 6833 // Read next point. 6834 curr, err := itr.input.Next() 6835 if err != nil { 6836 return nil, err 6837 } else if curr == nil { 6838 // Close all of the aggregators to flush any remaining points to emit. 6839 var points []IntegerPoint 6840 for _, rp := range itr.m { 6841 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 6842 if err := aggregator.Close(); err != nil { 6843 return nil, err 6844 } 6845 6846 pts := rp.Emitter.Emit() 6847 if len(pts) == 0 { 6848 continue 6849 } 6850 6851 for i := range pts { 6852 pts[i].Name = rp.Name 6853 pts[i].Tags = rp.Tags 6854 } 6855 points = append(points, pts...) 6856 } 6857 } 6858 6859 // Eliminate the aggregators and emitters. 6860 itr.m = nil 6861 return points, nil 6862 } else if curr.Nil { 6863 continue 6864 } 6865 tags := curr.Tags.Subset(itr.dims) 6866 6867 id := curr.Name 6868 if len(tags.m) > 0 { 6869 id += "\x00" + tags.ID() 6870 } 6871 6872 // Retrieve the aggregator for this name/tag combination or create one. 6873 rp := itr.m[id] 6874 if rp == nil { 6875 aggregator, emitter := itr.create() 6876 rp = &unsignedReduceIntegerPoint{ 6877 Name: curr.Name, 6878 Tags: tags, 6879 Aggregator: aggregator, 6880 Emitter: emitter, 6881 } 6882 itr.m[id] = rp 6883 } 6884 rp.Aggregator.AggregateUnsigned(curr) 6885 6886 // Attempt to emit points from the aggregator. 6887 points := rp.Emitter.Emit() 6888 if len(points) == 0 { 6889 continue 6890 } 6891 6892 for i := range points { 6893 points[i].Name = rp.Name 6894 points[i].Tags = rp.Tags 6895 } 6896 return points, nil 6897 } 6898} 6899 6900// unsignedReduceUnsignedIterator executes a reducer for every interval and buffers the result. 6901type unsignedReduceUnsignedIterator struct { 6902 input *bufUnsignedIterator 6903 create func() (UnsignedPointAggregator, UnsignedPointEmitter) 6904 dims []string 6905 opt IteratorOptions 6906 points []UnsignedPoint 6907 keepTags bool 6908} 6909 6910func newUnsignedReduceUnsignedIterator(input UnsignedIterator, opt IteratorOptions, createFn func() (UnsignedPointAggregator, UnsignedPointEmitter)) *unsignedReduceUnsignedIterator { 6911 return &unsignedReduceUnsignedIterator{ 6912 input: newBufUnsignedIterator(input), 6913 create: createFn, 6914 dims: opt.GetDimensions(), 6915 opt: opt, 6916 } 6917} 6918 6919// Stats returns stats from the input iterator. 6920func (itr *unsignedReduceUnsignedIterator) Stats() IteratorStats { return itr.input.Stats() } 6921 6922// Close closes the iterator and all child iterators. 6923func (itr *unsignedReduceUnsignedIterator) Close() error { return itr.input.Close() } 6924 6925// Next returns the minimum value for the next available interval. 6926func (itr *unsignedReduceUnsignedIterator) Next() (*UnsignedPoint, error) { 6927 // Calculate next window if we have no more points. 6928 if len(itr.points) == 0 { 6929 var err error 6930 itr.points, err = itr.reduce() 6931 if len(itr.points) == 0 { 6932 return nil, err 6933 } 6934 } 6935 6936 // Pop next point off the stack. 6937 p := &itr.points[len(itr.points)-1] 6938 itr.points = itr.points[:len(itr.points)-1] 6939 return p, nil 6940} 6941 6942// unsignedReduceUnsignedPoint stores the reduced data for a name/tag combination. 6943type unsignedReduceUnsignedPoint struct { 6944 Name string 6945 Tags Tags 6946 Aggregator UnsignedPointAggregator 6947 Emitter UnsignedPointEmitter 6948} 6949 6950// reduce executes fn once for every point in the next window. 6951// The previous value for the dimension is passed to fn. 6952func (itr *unsignedReduceUnsignedIterator) reduce() ([]UnsignedPoint, error) { 6953 // Calculate next window. 6954 var ( 6955 startTime, endTime int64 6956 window struct { 6957 name string 6958 tags string 6959 } 6960 ) 6961 for { 6962 p, err := itr.input.Next() 6963 if err != nil || p == nil { 6964 return nil, err 6965 } else if p.Nil { 6966 continue 6967 } 6968 6969 // Unread the point so it can be processed. 6970 itr.input.unread(p) 6971 startTime, endTime = itr.opt.Window(p.Time) 6972 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 6973 break 6974 } 6975 6976 // Create points by tags. 6977 m := make(map[string]*unsignedReduceUnsignedPoint) 6978 for { 6979 // Read next point. 6980 curr, err := itr.input.NextInWindow(startTime, endTime) 6981 if err != nil { 6982 return nil, err 6983 } else if curr == nil { 6984 break 6985 } else if curr.Nil { 6986 continue 6987 } else if curr.Name != window.name { 6988 itr.input.unread(curr) 6989 break 6990 } 6991 6992 // Ensure this point is within the same final window. 6993 if curr.Name != window.name { 6994 itr.input.unread(curr) 6995 break 6996 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 6997 itr.input.unread(curr) 6998 break 6999 } 7000 7001 // Retrieve the tags on this point for this level of the query. 7002 // This may be different than the bucket dimensions. 7003 tags := curr.Tags.Subset(itr.dims) 7004 id := tags.ID() 7005 7006 // Retrieve the aggregator for this name/tag combination or create one. 7007 rp := m[id] 7008 if rp == nil { 7009 aggregator, emitter := itr.create() 7010 rp = &unsignedReduceUnsignedPoint{ 7011 Name: curr.Name, 7012 Tags: tags, 7013 Aggregator: aggregator, 7014 Emitter: emitter, 7015 } 7016 m[id] = rp 7017 } 7018 rp.Aggregator.AggregateUnsigned(curr) 7019 } 7020 7021 keys := make([]string, 0, len(m)) 7022 for k := range m { 7023 keys = append(keys, k) 7024 } 7025 7026 // Reverse sort points by name & tag. 7027 // This ensures a consistent order of output. 7028 if len(keys) > 0 { 7029 var sorted sort.Interface = sort.StringSlice(keys) 7030 if itr.opt.Ascending { 7031 sorted = sort.Reverse(sorted) 7032 } 7033 sort.Sort(sorted) 7034 } 7035 7036 // Assume the points are already sorted until proven otherwise. 7037 sortedByTime := true 7038 // Emit the points for each name & tag combination. 7039 a := make([]UnsignedPoint, 0, len(m)) 7040 for _, k := range keys { 7041 rp := m[k] 7042 points := rp.Emitter.Emit() 7043 for i := len(points) - 1; i >= 0; i-- { 7044 points[i].Name = rp.Name 7045 if !itr.keepTags { 7046 points[i].Tags = rp.Tags 7047 } 7048 // Set the points time to the interval time if the reducer didn't provide one. 7049 if points[i].Time == ZeroTime { 7050 points[i].Time = startTime 7051 } else { 7052 sortedByTime = false 7053 } 7054 a = append(a, points[i]) 7055 } 7056 } 7057 // Points may be out of order. Perform a stable sort by time if requested. 7058 if !sortedByTime && itr.opt.Ordered { 7059 var sorted sort.Interface = unsignedPointsByTime(a) 7060 if itr.opt.Ascending { 7061 sorted = sort.Reverse(sorted) 7062 } 7063 sort.Stable(sorted) 7064 } 7065 return a, nil 7066} 7067 7068// unsignedStreamUnsignedIterator streams inputs into the iterator and emits points gradually. 7069type unsignedStreamUnsignedIterator struct { 7070 input *bufUnsignedIterator 7071 create func() (UnsignedPointAggregator, UnsignedPointEmitter) 7072 dims []string 7073 opt IteratorOptions 7074 m map[string]*unsignedReduceUnsignedPoint 7075 points []UnsignedPoint 7076} 7077 7078// newUnsignedStreamUnsignedIterator returns a new instance of unsignedStreamUnsignedIterator. 7079func newUnsignedStreamUnsignedIterator(input UnsignedIterator, createFn func() (UnsignedPointAggregator, UnsignedPointEmitter), opt IteratorOptions) *unsignedStreamUnsignedIterator { 7080 return &unsignedStreamUnsignedIterator{ 7081 input: newBufUnsignedIterator(input), 7082 create: createFn, 7083 dims: opt.GetDimensions(), 7084 opt: opt, 7085 m: make(map[string]*unsignedReduceUnsignedPoint), 7086 } 7087} 7088 7089// Stats returns stats from the input iterator. 7090func (itr *unsignedStreamUnsignedIterator) Stats() IteratorStats { return itr.input.Stats() } 7091 7092// Close closes the iterator and all child iterators. 7093func (itr *unsignedStreamUnsignedIterator) Close() error { return itr.input.Close() } 7094 7095// Next returns the next value for the stream iterator. 7096func (itr *unsignedStreamUnsignedIterator) Next() (*UnsignedPoint, error) { 7097 // Calculate next window if we have no more points. 7098 if len(itr.points) == 0 { 7099 var err error 7100 itr.points, err = itr.reduce() 7101 if len(itr.points) == 0 { 7102 return nil, err 7103 } 7104 } 7105 7106 // Pop next point off the stack. 7107 p := &itr.points[len(itr.points)-1] 7108 itr.points = itr.points[:len(itr.points)-1] 7109 return p, nil 7110} 7111 7112// reduce creates and manages aggregators for every point from the input. 7113// After aggregating a point, it always tries to emit a value using the emitter. 7114func (itr *unsignedStreamUnsignedIterator) reduce() ([]UnsignedPoint, error) { 7115 // We have already read all of the input points. 7116 if itr.m == nil { 7117 return nil, nil 7118 } 7119 7120 for { 7121 // Read next point. 7122 curr, err := itr.input.Next() 7123 if err != nil { 7124 return nil, err 7125 } else if curr == nil { 7126 // Close all of the aggregators to flush any remaining points to emit. 7127 var points []UnsignedPoint 7128 for _, rp := range itr.m { 7129 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 7130 if err := aggregator.Close(); err != nil { 7131 return nil, err 7132 } 7133 7134 pts := rp.Emitter.Emit() 7135 if len(pts) == 0 { 7136 continue 7137 } 7138 7139 for i := range pts { 7140 pts[i].Name = rp.Name 7141 pts[i].Tags = rp.Tags 7142 } 7143 points = append(points, pts...) 7144 } 7145 } 7146 7147 // Eliminate the aggregators and emitters. 7148 itr.m = nil 7149 return points, nil 7150 } else if curr.Nil { 7151 continue 7152 } 7153 tags := curr.Tags.Subset(itr.dims) 7154 7155 id := curr.Name 7156 if len(tags.m) > 0 { 7157 id += "\x00" + tags.ID() 7158 } 7159 7160 // Retrieve the aggregator for this name/tag combination or create one. 7161 rp := itr.m[id] 7162 if rp == nil { 7163 aggregator, emitter := itr.create() 7164 rp = &unsignedReduceUnsignedPoint{ 7165 Name: curr.Name, 7166 Tags: tags, 7167 Aggregator: aggregator, 7168 Emitter: emitter, 7169 } 7170 itr.m[id] = rp 7171 } 7172 rp.Aggregator.AggregateUnsigned(curr) 7173 7174 // Attempt to emit points from the aggregator. 7175 points := rp.Emitter.Emit() 7176 if len(points) == 0 { 7177 continue 7178 } 7179 7180 for i := range points { 7181 points[i].Name = rp.Name 7182 points[i].Tags = rp.Tags 7183 } 7184 return points, nil 7185 } 7186} 7187 7188// unsignedReduceStringIterator executes a reducer for every interval and buffers the result. 7189type unsignedReduceStringIterator struct { 7190 input *bufUnsignedIterator 7191 create func() (UnsignedPointAggregator, StringPointEmitter) 7192 dims []string 7193 opt IteratorOptions 7194 points []StringPoint 7195 keepTags bool 7196} 7197 7198func newUnsignedReduceStringIterator(input UnsignedIterator, opt IteratorOptions, createFn func() (UnsignedPointAggregator, StringPointEmitter)) *unsignedReduceStringIterator { 7199 return &unsignedReduceStringIterator{ 7200 input: newBufUnsignedIterator(input), 7201 create: createFn, 7202 dims: opt.GetDimensions(), 7203 opt: opt, 7204 } 7205} 7206 7207// Stats returns stats from the input iterator. 7208func (itr *unsignedReduceStringIterator) Stats() IteratorStats { return itr.input.Stats() } 7209 7210// Close closes the iterator and all child iterators. 7211func (itr *unsignedReduceStringIterator) Close() error { return itr.input.Close() } 7212 7213// Next returns the minimum value for the next available interval. 7214func (itr *unsignedReduceStringIterator) Next() (*StringPoint, error) { 7215 // Calculate next window if we have no more points. 7216 if len(itr.points) == 0 { 7217 var err error 7218 itr.points, err = itr.reduce() 7219 if len(itr.points) == 0 { 7220 return nil, err 7221 } 7222 } 7223 7224 // Pop next point off the stack. 7225 p := &itr.points[len(itr.points)-1] 7226 itr.points = itr.points[:len(itr.points)-1] 7227 return p, nil 7228} 7229 7230// unsignedReduceStringPoint stores the reduced data for a name/tag combination. 7231type unsignedReduceStringPoint struct { 7232 Name string 7233 Tags Tags 7234 Aggregator UnsignedPointAggregator 7235 Emitter StringPointEmitter 7236} 7237 7238// reduce executes fn once for every point in the next window. 7239// The previous value for the dimension is passed to fn. 7240func (itr *unsignedReduceStringIterator) reduce() ([]StringPoint, error) { 7241 // Calculate next window. 7242 var ( 7243 startTime, endTime int64 7244 window struct { 7245 name string 7246 tags string 7247 } 7248 ) 7249 for { 7250 p, err := itr.input.Next() 7251 if err != nil || p == nil { 7252 return nil, err 7253 } else if p.Nil { 7254 continue 7255 } 7256 7257 // Unread the point so it can be processed. 7258 itr.input.unread(p) 7259 startTime, endTime = itr.opt.Window(p.Time) 7260 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 7261 break 7262 } 7263 7264 // Create points by tags. 7265 m := make(map[string]*unsignedReduceStringPoint) 7266 for { 7267 // Read next point. 7268 curr, err := itr.input.NextInWindow(startTime, endTime) 7269 if err != nil { 7270 return nil, err 7271 } else if curr == nil { 7272 break 7273 } else if curr.Nil { 7274 continue 7275 } else if curr.Name != window.name { 7276 itr.input.unread(curr) 7277 break 7278 } 7279 7280 // Ensure this point is within the same final window. 7281 if curr.Name != window.name { 7282 itr.input.unread(curr) 7283 break 7284 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 7285 itr.input.unread(curr) 7286 break 7287 } 7288 7289 // Retrieve the tags on this point for this level of the query. 7290 // This may be different than the bucket dimensions. 7291 tags := curr.Tags.Subset(itr.dims) 7292 id := tags.ID() 7293 7294 // Retrieve the aggregator for this name/tag combination or create one. 7295 rp := m[id] 7296 if rp == nil { 7297 aggregator, emitter := itr.create() 7298 rp = &unsignedReduceStringPoint{ 7299 Name: curr.Name, 7300 Tags: tags, 7301 Aggregator: aggregator, 7302 Emitter: emitter, 7303 } 7304 m[id] = rp 7305 } 7306 rp.Aggregator.AggregateUnsigned(curr) 7307 } 7308 7309 keys := make([]string, 0, len(m)) 7310 for k := range m { 7311 keys = append(keys, k) 7312 } 7313 7314 // Reverse sort points by name & tag. 7315 // This ensures a consistent order of output. 7316 if len(keys) > 0 { 7317 var sorted sort.Interface = sort.StringSlice(keys) 7318 if itr.opt.Ascending { 7319 sorted = sort.Reverse(sorted) 7320 } 7321 sort.Sort(sorted) 7322 } 7323 7324 // Assume the points are already sorted until proven otherwise. 7325 sortedByTime := true 7326 // Emit the points for each name & tag combination. 7327 a := make([]StringPoint, 0, len(m)) 7328 for _, k := range keys { 7329 rp := m[k] 7330 points := rp.Emitter.Emit() 7331 for i := len(points) - 1; i >= 0; i-- { 7332 points[i].Name = rp.Name 7333 if !itr.keepTags { 7334 points[i].Tags = rp.Tags 7335 } 7336 // Set the points time to the interval time if the reducer didn't provide one. 7337 if points[i].Time == ZeroTime { 7338 points[i].Time = startTime 7339 } else { 7340 sortedByTime = false 7341 } 7342 a = append(a, points[i]) 7343 } 7344 } 7345 // Points may be out of order. Perform a stable sort by time if requested. 7346 if !sortedByTime && itr.opt.Ordered { 7347 var sorted sort.Interface = stringPointsByTime(a) 7348 if itr.opt.Ascending { 7349 sorted = sort.Reverse(sorted) 7350 } 7351 sort.Stable(sorted) 7352 } 7353 return a, nil 7354} 7355 7356// unsignedStreamStringIterator streams inputs into the iterator and emits points gradually. 7357type unsignedStreamStringIterator struct { 7358 input *bufUnsignedIterator 7359 create func() (UnsignedPointAggregator, StringPointEmitter) 7360 dims []string 7361 opt IteratorOptions 7362 m map[string]*unsignedReduceStringPoint 7363 points []StringPoint 7364} 7365 7366// newUnsignedStreamStringIterator returns a new instance of unsignedStreamStringIterator. 7367func newUnsignedStreamStringIterator(input UnsignedIterator, createFn func() (UnsignedPointAggregator, StringPointEmitter), opt IteratorOptions) *unsignedStreamStringIterator { 7368 return &unsignedStreamStringIterator{ 7369 input: newBufUnsignedIterator(input), 7370 create: createFn, 7371 dims: opt.GetDimensions(), 7372 opt: opt, 7373 m: make(map[string]*unsignedReduceStringPoint), 7374 } 7375} 7376 7377// Stats returns stats from the input iterator. 7378func (itr *unsignedStreamStringIterator) Stats() IteratorStats { return itr.input.Stats() } 7379 7380// Close closes the iterator and all child iterators. 7381func (itr *unsignedStreamStringIterator) Close() error { return itr.input.Close() } 7382 7383// Next returns the next value for the stream iterator. 7384func (itr *unsignedStreamStringIterator) Next() (*StringPoint, error) { 7385 // Calculate next window if we have no more points. 7386 if len(itr.points) == 0 { 7387 var err error 7388 itr.points, err = itr.reduce() 7389 if len(itr.points) == 0 { 7390 return nil, err 7391 } 7392 } 7393 7394 // Pop next point off the stack. 7395 p := &itr.points[len(itr.points)-1] 7396 itr.points = itr.points[:len(itr.points)-1] 7397 return p, nil 7398} 7399 7400// reduce creates and manages aggregators for every point from the input. 7401// After aggregating a point, it always tries to emit a value using the emitter. 7402func (itr *unsignedStreamStringIterator) reduce() ([]StringPoint, error) { 7403 // We have already read all of the input points. 7404 if itr.m == nil { 7405 return nil, nil 7406 } 7407 7408 for { 7409 // Read next point. 7410 curr, err := itr.input.Next() 7411 if err != nil { 7412 return nil, err 7413 } else if curr == nil { 7414 // Close all of the aggregators to flush any remaining points to emit. 7415 var points []StringPoint 7416 for _, rp := range itr.m { 7417 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 7418 if err := aggregator.Close(); err != nil { 7419 return nil, err 7420 } 7421 7422 pts := rp.Emitter.Emit() 7423 if len(pts) == 0 { 7424 continue 7425 } 7426 7427 for i := range pts { 7428 pts[i].Name = rp.Name 7429 pts[i].Tags = rp.Tags 7430 } 7431 points = append(points, pts...) 7432 } 7433 } 7434 7435 // Eliminate the aggregators and emitters. 7436 itr.m = nil 7437 return points, nil 7438 } else if curr.Nil { 7439 continue 7440 } 7441 tags := curr.Tags.Subset(itr.dims) 7442 7443 id := curr.Name 7444 if len(tags.m) > 0 { 7445 id += "\x00" + tags.ID() 7446 } 7447 7448 // Retrieve the aggregator for this name/tag combination or create one. 7449 rp := itr.m[id] 7450 if rp == nil { 7451 aggregator, emitter := itr.create() 7452 rp = &unsignedReduceStringPoint{ 7453 Name: curr.Name, 7454 Tags: tags, 7455 Aggregator: aggregator, 7456 Emitter: emitter, 7457 } 7458 itr.m[id] = rp 7459 } 7460 rp.Aggregator.AggregateUnsigned(curr) 7461 7462 // Attempt to emit points from the aggregator. 7463 points := rp.Emitter.Emit() 7464 if len(points) == 0 { 7465 continue 7466 } 7467 7468 for i := range points { 7469 points[i].Name = rp.Name 7470 points[i].Tags = rp.Tags 7471 } 7472 return points, nil 7473 } 7474} 7475 7476// unsignedReduceBooleanIterator executes a reducer for every interval and buffers the result. 7477type unsignedReduceBooleanIterator struct { 7478 input *bufUnsignedIterator 7479 create func() (UnsignedPointAggregator, BooleanPointEmitter) 7480 dims []string 7481 opt IteratorOptions 7482 points []BooleanPoint 7483 keepTags bool 7484} 7485 7486func newUnsignedReduceBooleanIterator(input UnsignedIterator, opt IteratorOptions, createFn func() (UnsignedPointAggregator, BooleanPointEmitter)) *unsignedReduceBooleanIterator { 7487 return &unsignedReduceBooleanIterator{ 7488 input: newBufUnsignedIterator(input), 7489 create: createFn, 7490 dims: opt.GetDimensions(), 7491 opt: opt, 7492 } 7493} 7494 7495// Stats returns stats from the input iterator. 7496func (itr *unsignedReduceBooleanIterator) Stats() IteratorStats { return itr.input.Stats() } 7497 7498// Close closes the iterator and all child iterators. 7499func (itr *unsignedReduceBooleanIterator) Close() error { return itr.input.Close() } 7500 7501// Next returns the minimum value for the next available interval. 7502func (itr *unsignedReduceBooleanIterator) Next() (*BooleanPoint, error) { 7503 // Calculate next window if we have no more points. 7504 if len(itr.points) == 0 { 7505 var err error 7506 itr.points, err = itr.reduce() 7507 if len(itr.points) == 0 { 7508 return nil, err 7509 } 7510 } 7511 7512 // Pop next point off the stack. 7513 p := &itr.points[len(itr.points)-1] 7514 itr.points = itr.points[:len(itr.points)-1] 7515 return p, nil 7516} 7517 7518// unsignedReduceBooleanPoint stores the reduced data for a name/tag combination. 7519type unsignedReduceBooleanPoint struct { 7520 Name string 7521 Tags Tags 7522 Aggregator UnsignedPointAggregator 7523 Emitter BooleanPointEmitter 7524} 7525 7526// reduce executes fn once for every point in the next window. 7527// The previous value for the dimension is passed to fn. 7528func (itr *unsignedReduceBooleanIterator) reduce() ([]BooleanPoint, error) { 7529 // Calculate next window. 7530 var ( 7531 startTime, endTime int64 7532 window struct { 7533 name string 7534 tags string 7535 } 7536 ) 7537 for { 7538 p, err := itr.input.Next() 7539 if err != nil || p == nil { 7540 return nil, err 7541 } else if p.Nil { 7542 continue 7543 } 7544 7545 // Unread the point so it can be processed. 7546 itr.input.unread(p) 7547 startTime, endTime = itr.opt.Window(p.Time) 7548 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 7549 break 7550 } 7551 7552 // Create points by tags. 7553 m := make(map[string]*unsignedReduceBooleanPoint) 7554 for { 7555 // Read next point. 7556 curr, err := itr.input.NextInWindow(startTime, endTime) 7557 if err != nil { 7558 return nil, err 7559 } else if curr == nil { 7560 break 7561 } else if curr.Nil { 7562 continue 7563 } else if curr.Name != window.name { 7564 itr.input.unread(curr) 7565 break 7566 } 7567 7568 // Ensure this point is within the same final window. 7569 if curr.Name != window.name { 7570 itr.input.unread(curr) 7571 break 7572 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 7573 itr.input.unread(curr) 7574 break 7575 } 7576 7577 // Retrieve the tags on this point for this level of the query. 7578 // This may be different than the bucket dimensions. 7579 tags := curr.Tags.Subset(itr.dims) 7580 id := tags.ID() 7581 7582 // Retrieve the aggregator for this name/tag combination or create one. 7583 rp := m[id] 7584 if rp == nil { 7585 aggregator, emitter := itr.create() 7586 rp = &unsignedReduceBooleanPoint{ 7587 Name: curr.Name, 7588 Tags: tags, 7589 Aggregator: aggregator, 7590 Emitter: emitter, 7591 } 7592 m[id] = rp 7593 } 7594 rp.Aggregator.AggregateUnsigned(curr) 7595 } 7596 7597 keys := make([]string, 0, len(m)) 7598 for k := range m { 7599 keys = append(keys, k) 7600 } 7601 7602 // Reverse sort points by name & tag. 7603 // This ensures a consistent order of output. 7604 if len(keys) > 0 { 7605 var sorted sort.Interface = sort.StringSlice(keys) 7606 if itr.opt.Ascending { 7607 sorted = sort.Reverse(sorted) 7608 } 7609 sort.Sort(sorted) 7610 } 7611 7612 // Assume the points are already sorted until proven otherwise. 7613 sortedByTime := true 7614 // Emit the points for each name & tag combination. 7615 a := make([]BooleanPoint, 0, len(m)) 7616 for _, k := range keys { 7617 rp := m[k] 7618 points := rp.Emitter.Emit() 7619 for i := len(points) - 1; i >= 0; i-- { 7620 points[i].Name = rp.Name 7621 if !itr.keepTags { 7622 points[i].Tags = rp.Tags 7623 } 7624 // Set the points time to the interval time if the reducer didn't provide one. 7625 if points[i].Time == ZeroTime { 7626 points[i].Time = startTime 7627 } else { 7628 sortedByTime = false 7629 } 7630 a = append(a, points[i]) 7631 } 7632 } 7633 // Points may be out of order. Perform a stable sort by time if requested. 7634 if !sortedByTime && itr.opt.Ordered { 7635 var sorted sort.Interface = booleanPointsByTime(a) 7636 if itr.opt.Ascending { 7637 sorted = sort.Reverse(sorted) 7638 } 7639 sort.Stable(sorted) 7640 } 7641 return a, nil 7642} 7643 7644// unsignedStreamBooleanIterator streams inputs into the iterator and emits points gradually. 7645type unsignedStreamBooleanIterator struct { 7646 input *bufUnsignedIterator 7647 create func() (UnsignedPointAggregator, BooleanPointEmitter) 7648 dims []string 7649 opt IteratorOptions 7650 m map[string]*unsignedReduceBooleanPoint 7651 points []BooleanPoint 7652} 7653 7654// newUnsignedStreamBooleanIterator returns a new instance of unsignedStreamBooleanIterator. 7655func newUnsignedStreamBooleanIterator(input UnsignedIterator, createFn func() (UnsignedPointAggregator, BooleanPointEmitter), opt IteratorOptions) *unsignedStreamBooleanIterator { 7656 return &unsignedStreamBooleanIterator{ 7657 input: newBufUnsignedIterator(input), 7658 create: createFn, 7659 dims: opt.GetDimensions(), 7660 opt: opt, 7661 m: make(map[string]*unsignedReduceBooleanPoint), 7662 } 7663} 7664 7665// Stats returns stats from the input iterator. 7666func (itr *unsignedStreamBooleanIterator) Stats() IteratorStats { return itr.input.Stats() } 7667 7668// Close closes the iterator and all child iterators. 7669func (itr *unsignedStreamBooleanIterator) Close() error { return itr.input.Close() } 7670 7671// Next returns the next value for the stream iterator. 7672func (itr *unsignedStreamBooleanIterator) Next() (*BooleanPoint, error) { 7673 // Calculate next window if we have no more points. 7674 if len(itr.points) == 0 { 7675 var err error 7676 itr.points, err = itr.reduce() 7677 if len(itr.points) == 0 { 7678 return nil, err 7679 } 7680 } 7681 7682 // Pop next point off the stack. 7683 p := &itr.points[len(itr.points)-1] 7684 itr.points = itr.points[:len(itr.points)-1] 7685 return p, nil 7686} 7687 7688// reduce creates and manages aggregators for every point from the input. 7689// After aggregating a point, it always tries to emit a value using the emitter. 7690func (itr *unsignedStreamBooleanIterator) reduce() ([]BooleanPoint, error) { 7691 // We have already read all of the input points. 7692 if itr.m == nil { 7693 return nil, nil 7694 } 7695 7696 for { 7697 // Read next point. 7698 curr, err := itr.input.Next() 7699 if err != nil { 7700 return nil, err 7701 } else if curr == nil { 7702 // Close all of the aggregators to flush any remaining points to emit. 7703 var points []BooleanPoint 7704 for _, rp := range itr.m { 7705 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 7706 if err := aggregator.Close(); err != nil { 7707 return nil, err 7708 } 7709 7710 pts := rp.Emitter.Emit() 7711 if len(pts) == 0 { 7712 continue 7713 } 7714 7715 for i := range pts { 7716 pts[i].Name = rp.Name 7717 pts[i].Tags = rp.Tags 7718 } 7719 points = append(points, pts...) 7720 } 7721 } 7722 7723 // Eliminate the aggregators and emitters. 7724 itr.m = nil 7725 return points, nil 7726 } else if curr.Nil { 7727 continue 7728 } 7729 tags := curr.Tags.Subset(itr.dims) 7730 7731 id := curr.Name 7732 if len(tags.m) > 0 { 7733 id += "\x00" + tags.ID() 7734 } 7735 7736 // Retrieve the aggregator for this name/tag combination or create one. 7737 rp := itr.m[id] 7738 if rp == nil { 7739 aggregator, emitter := itr.create() 7740 rp = &unsignedReduceBooleanPoint{ 7741 Name: curr.Name, 7742 Tags: tags, 7743 Aggregator: aggregator, 7744 Emitter: emitter, 7745 } 7746 itr.m[id] = rp 7747 } 7748 rp.Aggregator.AggregateUnsigned(curr) 7749 7750 // Attempt to emit points from the aggregator. 7751 points := rp.Emitter.Emit() 7752 if len(points) == 0 { 7753 continue 7754 } 7755 7756 for i := range points { 7757 points[i].Name = rp.Name 7758 points[i].Tags = rp.Tags 7759 } 7760 return points, nil 7761 } 7762} 7763 7764// unsignedDedupeIterator only outputs unique points. 7765// This differs from the DistinctIterator in that it compares all aux fields too. 7766// This iterator is relatively inefficient and should only be used on small 7767// datasets such as meta query results. 7768type unsignedDedupeIterator struct { 7769 input UnsignedIterator 7770 m map[string]struct{} // lookup of points already sent 7771} 7772 7773type unsignedIteratorMapper struct { 7774 cur Cursor 7775 row Row 7776 driver IteratorMap // which iterator to use for the primary value, can be nil 7777 fields []IteratorMap // which iterator to use for an aux field 7778 point UnsignedPoint 7779} 7780 7781func newUnsignedIteratorMapper(cur Cursor, driver IteratorMap, fields []IteratorMap, opt IteratorOptions) *unsignedIteratorMapper { 7782 return &unsignedIteratorMapper{ 7783 cur: cur, 7784 driver: driver, 7785 fields: fields, 7786 point: UnsignedPoint{ 7787 Aux: make([]interface{}, len(fields)), 7788 }, 7789 } 7790} 7791 7792func (itr *unsignedIteratorMapper) Next() (*UnsignedPoint, error) { 7793 if !itr.cur.Scan(&itr.row) { 7794 if err := itr.cur.Err(); err != nil { 7795 return nil, err 7796 } 7797 return nil, nil 7798 } 7799 7800 itr.point.Time = itr.row.Time 7801 itr.point.Name = itr.row.Series.Name 7802 itr.point.Tags = itr.row.Series.Tags 7803 7804 if itr.driver != nil { 7805 if v := itr.driver.Value(&itr.row); v != nil { 7806 if v, ok := castToUnsigned(v); ok { 7807 itr.point.Value = v 7808 itr.point.Nil = false 7809 } else { 7810 itr.point.Value = 0 7811 itr.point.Nil = true 7812 } 7813 } else { 7814 itr.point.Value = 0 7815 itr.point.Nil = true 7816 } 7817 } 7818 for i, f := range itr.fields { 7819 itr.point.Aux[i] = f.Value(&itr.row) 7820 } 7821 return &itr.point, nil 7822} 7823 7824func (itr *unsignedIteratorMapper) Stats() IteratorStats { 7825 return itr.cur.Stats() 7826} 7827 7828func (itr *unsignedIteratorMapper) Close() error { 7829 return itr.cur.Close() 7830} 7831 7832type unsignedFilterIterator struct { 7833 input UnsignedIterator 7834 cond influxql.Expr 7835 opt IteratorOptions 7836 m map[string]interface{} 7837} 7838 7839func newUnsignedFilterIterator(input UnsignedIterator, cond influxql.Expr, opt IteratorOptions) UnsignedIterator { 7840 // Strip out time conditions from the WHERE clause. 7841 // TODO(jsternberg): This should really be done for us when creating the IteratorOptions struct. 7842 n := influxql.RewriteFunc(influxql.CloneExpr(cond), func(n influxql.Node) influxql.Node { 7843 switch n := n.(type) { 7844 case *influxql.BinaryExpr: 7845 if n.LHS.String() == "time" { 7846 return &influxql.BooleanLiteral{Val: true} 7847 } 7848 } 7849 return n 7850 }) 7851 7852 cond, _ = n.(influxql.Expr) 7853 if cond == nil { 7854 return input 7855 } else if n, ok := cond.(*influxql.BooleanLiteral); ok && n.Val { 7856 return input 7857 } 7858 7859 return &unsignedFilterIterator{ 7860 input: input, 7861 cond: cond, 7862 opt: opt, 7863 m: make(map[string]interface{}), 7864 } 7865} 7866 7867func (itr *unsignedFilterIterator) Stats() IteratorStats { return itr.input.Stats() } 7868func (itr *unsignedFilterIterator) Close() error { return itr.input.Close() } 7869 7870func (itr *unsignedFilterIterator) Next() (*UnsignedPoint, error) { 7871 for { 7872 p, err := itr.input.Next() 7873 if err != nil || p == nil { 7874 return nil, err 7875 } 7876 7877 for i, ref := range itr.opt.Aux { 7878 itr.m[ref.Val] = p.Aux[i] 7879 } 7880 for k, v := range p.Tags.KeyValues() { 7881 itr.m[k] = v 7882 } 7883 7884 if !influxql.EvalBool(itr.cond, itr.m) { 7885 continue 7886 } 7887 return p, nil 7888 } 7889} 7890 7891type unsignedTagSubsetIterator struct { 7892 input UnsignedIterator 7893 point UnsignedPoint 7894 lastTags Tags 7895 dimensions []string 7896} 7897 7898func newUnsignedTagSubsetIterator(input UnsignedIterator, opt IteratorOptions) *unsignedTagSubsetIterator { 7899 return &unsignedTagSubsetIterator{ 7900 input: input, 7901 dimensions: opt.GetDimensions(), 7902 } 7903} 7904 7905func (itr *unsignedTagSubsetIterator) Next() (*UnsignedPoint, error) { 7906 p, err := itr.input.Next() 7907 if err != nil { 7908 return nil, err 7909 } else if p == nil { 7910 return nil, nil 7911 } 7912 7913 itr.point.Name = p.Name 7914 if !p.Tags.Equal(itr.lastTags) { 7915 itr.point.Tags = p.Tags.Subset(itr.dimensions) 7916 itr.lastTags = p.Tags 7917 } 7918 itr.point.Time = p.Time 7919 itr.point.Value = p.Value 7920 itr.point.Aux = p.Aux 7921 itr.point.Aggregated = p.Aggregated 7922 itr.point.Nil = p.Nil 7923 return &itr.point, nil 7924} 7925 7926func (itr *unsignedTagSubsetIterator) Stats() IteratorStats { 7927 return itr.input.Stats() 7928} 7929 7930func (itr *unsignedTagSubsetIterator) Close() error { 7931 return itr.input.Close() 7932} 7933 7934// newUnsignedDedupeIterator returns a new instance of unsignedDedupeIterator. 7935func newUnsignedDedupeIterator(input UnsignedIterator) *unsignedDedupeIterator { 7936 return &unsignedDedupeIterator{ 7937 input: input, 7938 m: make(map[string]struct{}), 7939 } 7940} 7941 7942// Stats returns stats from the input iterator. 7943func (itr *unsignedDedupeIterator) Stats() IteratorStats { return itr.input.Stats() } 7944 7945// Close closes the iterator and all child iterators. 7946func (itr *unsignedDedupeIterator) Close() error { return itr.input.Close() } 7947 7948// Next returns the next unique point from the input iterator. 7949func (itr *unsignedDedupeIterator) Next() (*UnsignedPoint, error) { 7950 for { 7951 // Read next point. 7952 p, err := itr.input.Next() 7953 if p == nil || err != nil { 7954 return nil, err 7955 } 7956 7957 // Serialize to bytes to store in lookup. 7958 buf, err := proto.Marshal(encodeUnsignedPoint(p)) 7959 if err != nil { 7960 return nil, err 7961 } 7962 7963 // If the point has already been output then move to the next point. 7964 if _, ok := itr.m[string(buf)]; ok { 7965 continue 7966 } 7967 7968 // Otherwise mark it as emitted and return point. 7969 itr.m[string(buf)] = struct{}{} 7970 return p, nil 7971 } 7972} 7973 7974// unsignedReaderIterator represents an iterator that streams from a reader. 7975type unsignedReaderIterator struct { 7976 r io.Reader 7977 dec *UnsignedPointDecoder 7978} 7979 7980// newUnsignedReaderIterator returns a new instance of unsignedReaderIterator. 7981func newUnsignedReaderIterator(ctx context.Context, r io.Reader, stats IteratorStats) *unsignedReaderIterator { 7982 dec := NewUnsignedPointDecoder(ctx, r) 7983 dec.stats = stats 7984 7985 return &unsignedReaderIterator{ 7986 r: r, 7987 dec: dec, 7988 } 7989} 7990 7991// Stats returns stats about points processed. 7992func (itr *unsignedReaderIterator) Stats() IteratorStats { return itr.dec.stats } 7993 7994// Close closes the underlying reader, if applicable. 7995func (itr *unsignedReaderIterator) Close() error { 7996 if r, ok := itr.r.(io.ReadCloser); ok { 7997 return r.Close() 7998 } 7999 return nil 8000} 8001 8002// Next returns the next point from the iterator. 8003func (itr *unsignedReaderIterator) Next() (*UnsignedPoint, error) { 8004 // OPTIMIZE(benbjohnson): Reuse point on iterator. 8005 8006 // Unmarshal next point. 8007 p := &UnsignedPoint{} 8008 if err := itr.dec.DecodeUnsignedPoint(p); err == io.EOF { 8009 return nil, nil 8010 } else if err != nil { 8011 return nil, err 8012 } 8013 return p, nil 8014} 8015 8016// StringIterator represents a stream of string points. 8017type StringIterator interface { 8018 Iterator 8019 Next() (*StringPoint, error) 8020} 8021 8022// newStringIterators converts a slice of Iterator to a slice of StringIterator. 8023// Drop and closes any iterator in itrs that is not a StringIterator and cannot 8024// be cast to a StringIterator. 8025func newStringIterators(itrs []Iterator) []StringIterator { 8026 a := make([]StringIterator, 0, len(itrs)) 8027 for _, itr := range itrs { 8028 switch itr := itr.(type) { 8029 case StringIterator: 8030 a = append(a, itr) 8031 default: 8032 itr.Close() 8033 } 8034 } 8035 return a 8036} 8037 8038// bufStringIterator represents a buffered StringIterator. 8039type bufStringIterator struct { 8040 itr StringIterator 8041 buf *StringPoint 8042} 8043 8044// newBufStringIterator returns a buffered StringIterator. 8045func newBufStringIterator(itr StringIterator) *bufStringIterator { 8046 return &bufStringIterator{itr: itr} 8047} 8048 8049// Stats returns statistics from the input iterator. 8050func (itr *bufStringIterator) Stats() IteratorStats { return itr.itr.Stats() } 8051 8052// Close closes the underlying iterator. 8053func (itr *bufStringIterator) Close() error { return itr.itr.Close() } 8054 8055// peek returns the next point without removing it from the iterator. 8056func (itr *bufStringIterator) peek() (*StringPoint, error) { 8057 p, err := itr.Next() 8058 if err != nil { 8059 return nil, err 8060 } 8061 itr.unread(p) 8062 return p, nil 8063} 8064 8065// peekTime returns the time of the next point. 8066// Returns zero time if no more points available. 8067func (itr *bufStringIterator) peekTime() (int64, error) { 8068 p, err := itr.peek() 8069 if p == nil || err != nil { 8070 return ZeroTime, err 8071 } 8072 return p.Time, nil 8073} 8074 8075// Next returns the current buffer, if exists, or calls the underlying iterator. 8076func (itr *bufStringIterator) Next() (*StringPoint, error) { 8077 buf := itr.buf 8078 if buf != nil { 8079 itr.buf = nil 8080 return buf, nil 8081 } 8082 return itr.itr.Next() 8083} 8084 8085// NextInWindow returns the next value if it is between [startTime, endTime). 8086// If the next value is outside the range then it is moved to the buffer. 8087func (itr *bufStringIterator) NextInWindow(startTime, endTime int64) (*StringPoint, error) { 8088 v, err := itr.Next() 8089 if v == nil || err != nil { 8090 return nil, err 8091 } else if t := v.Time; t >= endTime || t < startTime { 8092 itr.unread(v) 8093 return nil, nil 8094 } 8095 return v, nil 8096} 8097 8098// unread sets v to the buffer. It is read on the next call to Next(). 8099func (itr *bufStringIterator) unread(v *StringPoint) { itr.buf = v } 8100 8101// stringMergeIterator represents an iterator that combines multiple string iterators. 8102type stringMergeIterator struct { 8103 inputs []StringIterator 8104 heap *stringMergeHeap 8105 init bool 8106 8107 closed bool 8108 mu sync.RWMutex 8109 8110 // Current iterator and window. 8111 curr *stringMergeHeapItem 8112 window struct { 8113 name string 8114 tags string 8115 startTime int64 8116 endTime int64 8117 } 8118} 8119 8120// newStringMergeIterator returns a new instance of stringMergeIterator. 8121func newStringMergeIterator(inputs []StringIterator, opt IteratorOptions) *stringMergeIterator { 8122 itr := &stringMergeIterator{ 8123 inputs: inputs, 8124 heap: &stringMergeHeap{ 8125 items: make([]*stringMergeHeapItem, 0, len(inputs)), 8126 opt: opt, 8127 }, 8128 } 8129 8130 // Initialize heap items. 8131 for _, input := range inputs { 8132 // Wrap in buffer, ignore any inputs without anymore points. 8133 bufInput := newBufStringIterator(input) 8134 8135 // Append to the heap. 8136 itr.heap.items = append(itr.heap.items, &stringMergeHeapItem{itr: bufInput}) 8137 } 8138 8139 return itr 8140} 8141 8142// Stats returns an aggregation of stats from the underlying iterators. 8143func (itr *stringMergeIterator) Stats() IteratorStats { 8144 var stats IteratorStats 8145 for _, input := range itr.inputs { 8146 stats.Add(input.Stats()) 8147 } 8148 return stats 8149} 8150 8151// Close closes the underlying iterators. 8152func (itr *stringMergeIterator) Close() error { 8153 itr.mu.Lock() 8154 defer itr.mu.Unlock() 8155 8156 for _, input := range itr.inputs { 8157 input.Close() 8158 } 8159 itr.curr = nil 8160 itr.inputs = nil 8161 itr.heap.items = nil 8162 itr.closed = true 8163 return nil 8164} 8165 8166// Next returns the next point from the iterator. 8167func (itr *stringMergeIterator) Next() (*StringPoint, error) { 8168 itr.mu.RLock() 8169 defer itr.mu.RUnlock() 8170 if itr.closed { 8171 return nil, nil 8172 } 8173 8174 // Initialize the heap. This needs to be done lazily on the first call to this iterator 8175 // so that iterator initialization done through the Select() call returns quickly. 8176 // Queries can only be interrupted after the Select() call completes so any operations 8177 // done during iterator creation cannot be interrupted, which is why we do it here 8178 // instead so an interrupt can happen while initializing the heap. 8179 if !itr.init { 8180 items := itr.heap.items 8181 itr.heap.items = make([]*stringMergeHeapItem, 0, len(items)) 8182 for _, item := range items { 8183 if p, err := item.itr.peek(); err != nil { 8184 return nil, err 8185 } else if p == nil { 8186 continue 8187 } 8188 itr.heap.items = append(itr.heap.items, item) 8189 } 8190 heap.Init(itr.heap) 8191 itr.init = true 8192 } 8193 8194 for { 8195 // Retrieve the next iterator if we don't have one. 8196 if itr.curr == nil { 8197 if len(itr.heap.items) == 0 { 8198 return nil, nil 8199 } 8200 itr.curr = heap.Pop(itr.heap).(*stringMergeHeapItem) 8201 8202 // Read point and set current window. 8203 p, err := itr.curr.itr.Next() 8204 if err != nil { 8205 return nil, err 8206 } 8207 tags := p.Tags.Subset(itr.heap.opt.Dimensions) 8208 itr.window.name, itr.window.tags = p.Name, tags.ID() 8209 itr.window.startTime, itr.window.endTime = itr.heap.opt.Window(p.Time) 8210 return p, nil 8211 } 8212 8213 // Read the next point from the current iterator. 8214 p, err := itr.curr.itr.Next() 8215 if err != nil { 8216 return nil, err 8217 } 8218 8219 // If there are no more points then remove iterator from heap and find next. 8220 if p == nil { 8221 itr.curr = nil 8222 continue 8223 } 8224 8225 // Check if the point is inside of our current window. 8226 inWindow := true 8227 if window := itr.window; window.name != p.Name { 8228 inWindow = false 8229 } else if tags := p.Tags.Subset(itr.heap.opt.Dimensions); window.tags != tags.ID() { 8230 inWindow = false 8231 } else if opt := itr.heap.opt; opt.Ascending && p.Time >= window.endTime { 8232 inWindow = false 8233 } else if !opt.Ascending && p.Time < window.startTime { 8234 inWindow = false 8235 } 8236 8237 // If it's outside our window then push iterator back on the heap and find new iterator. 8238 if !inWindow { 8239 itr.curr.itr.unread(p) 8240 heap.Push(itr.heap, itr.curr) 8241 itr.curr = nil 8242 continue 8243 } 8244 8245 return p, nil 8246 } 8247} 8248 8249// stringMergeHeap represents a heap of stringMergeHeapItems. 8250// Items are sorted by their next window and then by name/tags. 8251type stringMergeHeap struct { 8252 opt IteratorOptions 8253 items []*stringMergeHeapItem 8254} 8255 8256func (h *stringMergeHeap) Len() int { return len(h.items) } 8257func (h *stringMergeHeap) Swap(i, j int) { h.items[i], h.items[j] = h.items[j], h.items[i] } 8258func (h *stringMergeHeap) Less(i, j int) bool { 8259 x, err := h.items[i].itr.peek() 8260 if err != nil { 8261 return true 8262 } 8263 y, err := h.items[j].itr.peek() 8264 if err != nil { 8265 return false 8266 } 8267 8268 if h.opt.Ascending { 8269 if x.Name != y.Name { 8270 return x.Name < y.Name 8271 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); xTags.ID() != yTags.ID() { 8272 return xTags.ID() < yTags.ID() 8273 } 8274 } else { 8275 if x.Name != y.Name { 8276 return x.Name > y.Name 8277 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); xTags.ID() != yTags.ID() { 8278 return xTags.ID() > yTags.ID() 8279 } 8280 } 8281 8282 xt, _ := h.opt.Window(x.Time) 8283 yt, _ := h.opt.Window(y.Time) 8284 8285 if h.opt.Ascending { 8286 return xt < yt 8287 } 8288 return xt > yt 8289} 8290 8291func (h *stringMergeHeap) Push(x interface{}) { 8292 h.items = append(h.items, x.(*stringMergeHeapItem)) 8293} 8294 8295func (h *stringMergeHeap) Pop() interface{} { 8296 old := h.items 8297 n := len(old) 8298 item := old[n-1] 8299 h.items = old[0 : n-1] 8300 return item 8301} 8302 8303type stringMergeHeapItem struct { 8304 itr *bufStringIterator 8305} 8306 8307// stringSortedMergeIterator is an iterator that sorts and merges multiple iterators into one. 8308type stringSortedMergeIterator struct { 8309 inputs []StringIterator 8310 heap *stringSortedMergeHeap 8311 init bool 8312} 8313 8314// newStringSortedMergeIterator returns an instance of stringSortedMergeIterator. 8315func newStringSortedMergeIterator(inputs []StringIterator, opt IteratorOptions) Iterator { 8316 itr := &stringSortedMergeIterator{ 8317 inputs: inputs, 8318 heap: &stringSortedMergeHeap{ 8319 items: make([]*stringSortedMergeHeapItem, 0, len(inputs)), 8320 opt: opt, 8321 }, 8322 } 8323 8324 // Initialize heap items. 8325 for _, input := range inputs { 8326 // Append to the heap. 8327 itr.heap.items = append(itr.heap.items, &stringSortedMergeHeapItem{itr: input}) 8328 } 8329 8330 return itr 8331} 8332 8333// Stats returns an aggregation of stats from the underlying iterators. 8334func (itr *stringSortedMergeIterator) Stats() IteratorStats { 8335 var stats IteratorStats 8336 for _, input := range itr.inputs { 8337 stats.Add(input.Stats()) 8338 } 8339 return stats 8340} 8341 8342// Close closes the underlying iterators. 8343func (itr *stringSortedMergeIterator) Close() error { 8344 for _, input := range itr.inputs { 8345 input.Close() 8346 } 8347 return nil 8348} 8349 8350// Next returns the next points from the iterator. 8351func (itr *stringSortedMergeIterator) Next() (*StringPoint, error) { return itr.pop() } 8352 8353// pop returns the next point from the heap. 8354// Reads the next point from item's cursor and puts it back on the heap. 8355func (itr *stringSortedMergeIterator) pop() (*StringPoint, error) { 8356 // Initialize the heap. See the MergeIterator to see why this has to be done lazily. 8357 if !itr.init { 8358 items := itr.heap.items 8359 itr.heap.items = make([]*stringSortedMergeHeapItem, 0, len(items)) 8360 for _, item := range items { 8361 var err error 8362 if item.point, err = item.itr.Next(); err != nil { 8363 return nil, err 8364 } else if item.point == nil { 8365 continue 8366 } 8367 itr.heap.items = append(itr.heap.items, item) 8368 } 8369 heap.Init(itr.heap) 8370 itr.init = true 8371 } 8372 8373 if len(itr.heap.items) == 0 { 8374 return nil, nil 8375 } 8376 8377 // Read the next item from the heap. 8378 item := heap.Pop(itr.heap).(*stringSortedMergeHeapItem) 8379 if item.err != nil { 8380 return nil, item.err 8381 } else if item.point == nil { 8382 return nil, nil 8383 } 8384 8385 // Copy the point for return. 8386 p := item.point.Clone() 8387 8388 // Read the next item from the cursor. Push back to heap if one exists. 8389 if item.point, item.err = item.itr.Next(); item.point != nil { 8390 heap.Push(itr.heap, item) 8391 } 8392 8393 return p, nil 8394} 8395 8396// stringSortedMergeHeap represents a heap of stringSortedMergeHeapItems. 8397// Items are sorted with the following priority: 8398// - By their measurement name; 8399// - By their tag keys/values; 8400// - By time; or 8401// - By their Aux field values. 8402// 8403type stringSortedMergeHeap struct { 8404 opt IteratorOptions 8405 items []*stringSortedMergeHeapItem 8406} 8407 8408func (h *stringSortedMergeHeap) Len() int { return len(h.items) } 8409func (h *stringSortedMergeHeap) Swap(i, j int) { h.items[i], h.items[j] = h.items[j], h.items[i] } 8410func (h *stringSortedMergeHeap) Less(i, j int) bool { 8411 x, y := h.items[i].point, h.items[j].point 8412 8413 if h.opt.Ascending { 8414 if x.Name != y.Name { 8415 return x.Name < y.Name 8416 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); !xTags.Equals(&yTags) { 8417 return xTags.ID() < yTags.ID() 8418 } 8419 8420 if x.Time != y.Time { 8421 return x.Time < y.Time 8422 } 8423 8424 if len(x.Aux) > 0 && len(x.Aux) == len(y.Aux) { 8425 for i := 0; i < len(x.Aux); i++ { 8426 v1, ok1 := x.Aux[i].(string) 8427 v2, ok2 := y.Aux[i].(string) 8428 if !ok1 || !ok2 { 8429 // Unsupported types used in Aux fields. Maybe they 8430 // need to be added here? 8431 return false 8432 } else if v1 == v2 { 8433 continue 8434 } 8435 return v1 < v2 8436 } 8437 } 8438 return false // Times and/or Aux fields are equal. 8439 } 8440 8441 if x.Name != y.Name { 8442 return x.Name > y.Name 8443 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); !xTags.Equals(&yTags) { 8444 return xTags.ID() > yTags.ID() 8445 } 8446 8447 if x.Time != y.Time { 8448 return x.Time > y.Time 8449 } 8450 8451 if len(x.Aux) > 0 && len(x.Aux) == len(y.Aux) { 8452 for i := 0; i < len(x.Aux); i++ { 8453 v1, ok1 := x.Aux[i].(string) 8454 v2, ok2 := y.Aux[i].(string) 8455 if !ok1 || !ok2 { 8456 // Unsupported types used in Aux fields. Maybe they 8457 // need to be added here? 8458 return false 8459 } else if v1 == v2 { 8460 continue 8461 } 8462 return v1 > v2 8463 } 8464 } 8465 return false // Times and/or Aux fields are equal. 8466} 8467 8468func (h *stringSortedMergeHeap) Push(x interface{}) { 8469 h.items = append(h.items, x.(*stringSortedMergeHeapItem)) 8470} 8471 8472func (h *stringSortedMergeHeap) Pop() interface{} { 8473 old := h.items 8474 n := len(old) 8475 item := old[n-1] 8476 h.items = old[0 : n-1] 8477 return item 8478} 8479 8480type stringSortedMergeHeapItem struct { 8481 point *StringPoint 8482 err error 8483 itr StringIterator 8484} 8485 8486// stringIteratorScanner scans the results of a StringIterator into a map. 8487type stringIteratorScanner struct { 8488 input *bufStringIterator 8489 err error 8490 keys []influxql.VarRef 8491 defaultValue interface{} 8492} 8493 8494// newStringIteratorScanner creates a new IteratorScanner. 8495func newStringIteratorScanner(input StringIterator, keys []influxql.VarRef, defaultValue interface{}) *stringIteratorScanner { 8496 return &stringIteratorScanner{ 8497 input: newBufStringIterator(input), 8498 keys: keys, 8499 defaultValue: defaultValue, 8500 } 8501} 8502 8503func (s *stringIteratorScanner) Peek() (int64, string, Tags) { 8504 if s.err != nil { 8505 return ZeroTime, "", Tags{} 8506 } 8507 8508 p, err := s.input.peek() 8509 if err != nil { 8510 s.err = err 8511 return ZeroTime, "", Tags{} 8512 } else if p == nil { 8513 return ZeroTime, "", Tags{} 8514 } 8515 return p.Time, p.Name, p.Tags 8516} 8517 8518func (s *stringIteratorScanner) ScanAt(ts int64, name string, tags Tags, m map[string]interface{}) { 8519 if s.err != nil { 8520 return 8521 } 8522 8523 p, err := s.input.Next() 8524 if err != nil { 8525 s.err = err 8526 return 8527 } else if p == nil { 8528 s.useDefaults(m) 8529 return 8530 } else if p.Time != ts || p.Name != name || !p.Tags.Equals(&tags) { 8531 s.useDefaults(m) 8532 s.input.unread(p) 8533 return 8534 } 8535 8536 if k := s.keys[0]; k.Val != "" { 8537 if p.Nil { 8538 if s.defaultValue != SkipDefault { 8539 m[k.Val] = castToType(s.defaultValue, k.Type) 8540 } 8541 } else { 8542 m[k.Val] = p.Value 8543 } 8544 } 8545 for i, v := range p.Aux { 8546 k := s.keys[i+1] 8547 switch v.(type) { 8548 case float64, int64, uint64, string, bool: 8549 m[k.Val] = v 8550 default: 8551 // Insert the fill value if one was specified. 8552 if s.defaultValue != SkipDefault { 8553 m[k.Val] = castToType(s.defaultValue, k.Type) 8554 } 8555 } 8556 } 8557} 8558 8559func (s *stringIteratorScanner) useDefaults(m map[string]interface{}) { 8560 if s.defaultValue == SkipDefault { 8561 return 8562 } 8563 for _, k := range s.keys { 8564 if k.Val == "" { 8565 continue 8566 } 8567 m[k.Val] = castToType(s.defaultValue, k.Type) 8568 } 8569} 8570 8571func (s *stringIteratorScanner) Stats() IteratorStats { return s.input.Stats() } 8572func (s *stringIteratorScanner) Err() error { return s.err } 8573func (s *stringIteratorScanner) Close() error { return s.input.Close() } 8574 8575// stringParallelIterator represents an iterator that pulls data in a separate goroutine. 8576type stringParallelIterator struct { 8577 input StringIterator 8578 ch chan stringPointError 8579 8580 once sync.Once 8581 closing chan struct{} 8582 wg sync.WaitGroup 8583} 8584 8585// newStringParallelIterator returns a new instance of stringParallelIterator. 8586func newStringParallelIterator(input StringIterator) *stringParallelIterator { 8587 itr := &stringParallelIterator{ 8588 input: input, 8589 ch: make(chan stringPointError, 256), 8590 closing: make(chan struct{}), 8591 } 8592 itr.wg.Add(1) 8593 go itr.monitor() 8594 return itr 8595} 8596 8597// Stats returns stats from the underlying iterator. 8598func (itr *stringParallelIterator) Stats() IteratorStats { return itr.input.Stats() } 8599 8600// Close closes the underlying iterators. 8601func (itr *stringParallelIterator) Close() error { 8602 itr.once.Do(func() { close(itr.closing) }) 8603 itr.wg.Wait() 8604 return itr.input.Close() 8605} 8606 8607// Next returns the next point from the iterator. 8608func (itr *stringParallelIterator) Next() (*StringPoint, error) { 8609 v, ok := <-itr.ch 8610 if !ok { 8611 return nil, io.EOF 8612 } 8613 return v.point, v.err 8614} 8615 8616// monitor runs in a separate goroutine and actively pulls the next point. 8617func (itr *stringParallelIterator) monitor() { 8618 defer close(itr.ch) 8619 defer itr.wg.Done() 8620 8621 for { 8622 // Read next point. 8623 p, err := itr.input.Next() 8624 if p != nil { 8625 p = p.Clone() 8626 } 8627 8628 select { 8629 case <-itr.closing: 8630 return 8631 case itr.ch <- stringPointError{point: p, err: err}: 8632 } 8633 } 8634} 8635 8636type stringPointError struct { 8637 point *StringPoint 8638 err error 8639} 8640 8641// stringLimitIterator represents an iterator that limits points per group. 8642type stringLimitIterator struct { 8643 input StringIterator 8644 opt IteratorOptions 8645 n int 8646 8647 prev struct { 8648 name string 8649 tags Tags 8650 } 8651} 8652 8653// newStringLimitIterator returns a new instance of stringLimitIterator. 8654func newStringLimitIterator(input StringIterator, opt IteratorOptions) *stringLimitIterator { 8655 return &stringLimitIterator{ 8656 input: input, 8657 opt: opt, 8658 } 8659} 8660 8661// Stats returns stats from the underlying iterator. 8662func (itr *stringLimitIterator) Stats() IteratorStats { return itr.input.Stats() } 8663 8664// Close closes the underlying iterators. 8665func (itr *stringLimitIterator) Close() error { return itr.input.Close() } 8666 8667// Next returns the next point from the iterator. 8668func (itr *stringLimitIterator) Next() (*StringPoint, error) { 8669 for { 8670 p, err := itr.input.Next() 8671 if p == nil || err != nil { 8672 return nil, err 8673 } 8674 8675 // Reset window and counter if a new window is encountered. 8676 if p.Name != itr.prev.name || !p.Tags.Equals(&itr.prev.tags) { 8677 itr.prev.name = p.Name 8678 itr.prev.tags = p.Tags 8679 itr.n = 0 8680 } 8681 8682 // Increment counter. 8683 itr.n++ 8684 8685 // Read next point if not beyond the offset. 8686 if itr.n <= itr.opt.Offset { 8687 continue 8688 } 8689 8690 // Read next point if we're beyond the limit. 8691 if itr.opt.Limit > 0 && (itr.n-itr.opt.Offset) > itr.opt.Limit { 8692 continue 8693 } 8694 8695 return p, nil 8696 } 8697} 8698 8699type stringFillIterator struct { 8700 input *bufStringIterator 8701 prev StringPoint 8702 startTime int64 8703 endTime int64 8704 auxFields []interface{} 8705 init bool 8706 opt IteratorOptions 8707 8708 window struct { 8709 name string 8710 tags Tags 8711 time int64 8712 offset int64 8713 } 8714} 8715 8716func newStringFillIterator(input StringIterator, expr influxql.Expr, opt IteratorOptions) *stringFillIterator { 8717 if opt.Fill == influxql.NullFill { 8718 if expr, ok := expr.(*influxql.Call); ok && expr.Name == "count" { 8719 opt.Fill = influxql.NumberFill 8720 opt.FillValue = "" 8721 } 8722 } 8723 8724 var startTime, endTime int64 8725 if opt.Ascending { 8726 startTime, _ = opt.Window(opt.StartTime) 8727 endTime, _ = opt.Window(opt.EndTime) 8728 } else { 8729 startTime, _ = opt.Window(opt.EndTime) 8730 endTime, _ = opt.Window(opt.StartTime) 8731 } 8732 8733 var auxFields []interface{} 8734 if len(opt.Aux) > 0 { 8735 auxFields = make([]interface{}, len(opt.Aux)) 8736 } 8737 8738 return &stringFillIterator{ 8739 input: newBufStringIterator(input), 8740 prev: StringPoint{Nil: true}, 8741 startTime: startTime, 8742 endTime: endTime, 8743 auxFields: auxFields, 8744 opt: opt, 8745 } 8746} 8747 8748func (itr *stringFillIterator) Stats() IteratorStats { return itr.input.Stats() } 8749func (itr *stringFillIterator) Close() error { return itr.input.Close() } 8750 8751func (itr *stringFillIterator) Next() (*StringPoint, error) { 8752 if !itr.init { 8753 p, err := itr.input.peek() 8754 if p == nil || err != nil { 8755 return nil, err 8756 } 8757 itr.window.name, itr.window.tags = p.Name, p.Tags 8758 itr.window.time = itr.startTime 8759 if itr.startTime == influxql.MinTime { 8760 itr.window.time, _ = itr.opt.Window(p.Time) 8761 } 8762 if itr.opt.Location != nil { 8763 _, itr.window.offset = itr.opt.Zone(itr.window.time) 8764 } 8765 itr.init = true 8766 } 8767 8768 p, err := itr.input.Next() 8769 if err != nil { 8770 return nil, err 8771 } 8772 8773 // Check if the next point is outside of our window or is nil. 8774 if p == nil || p.Name != itr.window.name || p.Tags.ID() != itr.window.tags.ID() { 8775 // If we are inside of an interval, unread the point and continue below to 8776 // constructing a new point. 8777 if itr.opt.Ascending && itr.window.time <= itr.endTime { 8778 itr.input.unread(p) 8779 p = nil 8780 goto CONSTRUCT 8781 } else if !itr.opt.Ascending && itr.window.time >= itr.endTime && itr.endTime != influxql.MinTime { 8782 itr.input.unread(p) 8783 p = nil 8784 goto CONSTRUCT 8785 } 8786 8787 // We are *not* in a current interval. If there is no next point, 8788 // we are at the end of all intervals. 8789 if p == nil { 8790 return nil, nil 8791 } 8792 8793 // Set the new interval. 8794 itr.window.name, itr.window.tags = p.Name, p.Tags 8795 itr.window.time = itr.startTime 8796 if itr.window.time == influxql.MinTime { 8797 itr.window.time, _ = itr.opt.Window(p.Time) 8798 } 8799 if itr.opt.Location != nil { 8800 _, itr.window.offset = itr.opt.Zone(itr.window.time) 8801 } 8802 itr.prev = StringPoint{Nil: true} 8803 } 8804 8805 // Check if the point is our next expected point. 8806CONSTRUCT: 8807 if p == nil || (itr.opt.Ascending && p.Time > itr.window.time) || (!itr.opt.Ascending && p.Time < itr.window.time) { 8808 if p != nil { 8809 itr.input.unread(p) 8810 } 8811 8812 p = &StringPoint{ 8813 Name: itr.window.name, 8814 Tags: itr.window.tags, 8815 Time: itr.window.time, 8816 Aux: itr.auxFields, 8817 } 8818 8819 switch itr.opt.Fill { 8820 case influxql.LinearFill: 8821 fallthrough 8822 case influxql.NullFill: 8823 p.Nil = true 8824 case influxql.NumberFill: 8825 p.Value, _ = castToString(itr.opt.FillValue) 8826 case influxql.PreviousFill: 8827 if !itr.prev.Nil { 8828 p.Value = itr.prev.Value 8829 p.Nil = itr.prev.Nil 8830 } else { 8831 p.Nil = true 8832 } 8833 } 8834 } else { 8835 itr.prev = *p 8836 } 8837 8838 // Advance the expected time. Do not advance to a new window here 8839 // as there may be lingering points with the same timestamp in the previous 8840 // window. 8841 if itr.opt.Ascending { 8842 itr.window.time += int64(itr.opt.Interval.Duration) 8843 } else { 8844 itr.window.time -= int64(itr.opt.Interval.Duration) 8845 } 8846 8847 // Check to see if we have passed over an offset change and adjust the time 8848 // to account for this new offset. 8849 if itr.opt.Location != nil { 8850 if _, offset := itr.opt.Zone(itr.window.time - 1); offset != itr.window.offset { 8851 diff := itr.window.offset - offset 8852 if abs(diff) < int64(itr.opt.Interval.Duration) { 8853 itr.window.time += diff 8854 } 8855 itr.window.offset = offset 8856 } 8857 } 8858 return p, nil 8859} 8860 8861// stringIntervalIterator represents a string implementation of IntervalIterator. 8862type stringIntervalIterator struct { 8863 input StringIterator 8864 opt IteratorOptions 8865} 8866 8867func newStringIntervalIterator(input StringIterator, opt IteratorOptions) *stringIntervalIterator { 8868 return &stringIntervalIterator{input: input, opt: opt} 8869} 8870 8871func (itr *stringIntervalIterator) Stats() IteratorStats { return itr.input.Stats() } 8872func (itr *stringIntervalIterator) Close() error { return itr.input.Close() } 8873 8874func (itr *stringIntervalIterator) Next() (*StringPoint, error) { 8875 p, err := itr.input.Next() 8876 if p == nil || err != nil { 8877 return nil, err 8878 } 8879 p.Time, _ = itr.opt.Window(p.Time) 8880 // If we see the minimum allowable time, set the time to zero so we don't 8881 // break the default returned time for aggregate queries without times. 8882 if p.Time == influxql.MinTime { 8883 p.Time = 0 8884 } 8885 return p, nil 8886} 8887 8888// stringInterruptIterator represents a string implementation of InterruptIterator. 8889type stringInterruptIterator struct { 8890 input StringIterator 8891 closing <-chan struct{} 8892 count int 8893} 8894 8895func newStringInterruptIterator(input StringIterator, closing <-chan struct{}) *stringInterruptIterator { 8896 return &stringInterruptIterator{input: input, closing: closing} 8897} 8898 8899func (itr *stringInterruptIterator) Stats() IteratorStats { return itr.input.Stats() } 8900func (itr *stringInterruptIterator) Close() error { return itr.input.Close() } 8901 8902func (itr *stringInterruptIterator) Next() (*StringPoint, error) { 8903 // Only check if the channel is closed every N points. This 8904 // intentionally checks on both 0 and N so that if the iterator 8905 // has been interrupted before the first point is emitted it will 8906 // not emit any points. 8907 if itr.count&0xFF == 0xFF { 8908 select { 8909 case <-itr.closing: 8910 return nil, itr.Close() 8911 default: 8912 // Reset iterator count to zero and fall through to emit the next point. 8913 itr.count = 0 8914 } 8915 } 8916 8917 // Increment the counter for every point read. 8918 itr.count++ 8919 return itr.input.Next() 8920} 8921 8922// stringCloseInterruptIterator represents a string implementation of CloseInterruptIterator. 8923type stringCloseInterruptIterator struct { 8924 input StringIterator 8925 closing <-chan struct{} 8926 done chan struct{} 8927 once sync.Once 8928} 8929 8930func newStringCloseInterruptIterator(input StringIterator, closing <-chan struct{}) *stringCloseInterruptIterator { 8931 itr := &stringCloseInterruptIterator{ 8932 input: input, 8933 closing: closing, 8934 done: make(chan struct{}), 8935 } 8936 go itr.monitor() 8937 return itr 8938} 8939 8940func (itr *stringCloseInterruptIterator) monitor() { 8941 select { 8942 case <-itr.closing: 8943 itr.Close() 8944 case <-itr.done: 8945 } 8946} 8947 8948func (itr *stringCloseInterruptIterator) Stats() IteratorStats { 8949 return itr.input.Stats() 8950} 8951 8952func (itr *stringCloseInterruptIterator) Close() error { 8953 itr.once.Do(func() { 8954 close(itr.done) 8955 itr.input.Close() 8956 }) 8957 return nil 8958} 8959 8960func (itr *stringCloseInterruptIterator) Next() (*StringPoint, error) { 8961 p, err := itr.input.Next() 8962 if err != nil { 8963 // Check if the iterator was closed. 8964 select { 8965 case <-itr.done: 8966 return nil, nil 8967 default: 8968 return nil, err 8969 } 8970 } 8971 return p, nil 8972} 8973 8974// stringReduceFloatIterator executes a reducer for every interval and buffers the result. 8975type stringReduceFloatIterator struct { 8976 input *bufStringIterator 8977 create func() (StringPointAggregator, FloatPointEmitter) 8978 dims []string 8979 opt IteratorOptions 8980 points []FloatPoint 8981 keepTags bool 8982} 8983 8984func newStringReduceFloatIterator(input StringIterator, opt IteratorOptions, createFn func() (StringPointAggregator, FloatPointEmitter)) *stringReduceFloatIterator { 8985 return &stringReduceFloatIterator{ 8986 input: newBufStringIterator(input), 8987 create: createFn, 8988 dims: opt.GetDimensions(), 8989 opt: opt, 8990 } 8991} 8992 8993// Stats returns stats from the input iterator. 8994func (itr *stringReduceFloatIterator) Stats() IteratorStats { return itr.input.Stats() } 8995 8996// Close closes the iterator and all child iterators. 8997func (itr *stringReduceFloatIterator) Close() error { return itr.input.Close() } 8998 8999// Next returns the minimum value for the next available interval. 9000func (itr *stringReduceFloatIterator) Next() (*FloatPoint, error) { 9001 // Calculate next window if we have no more points. 9002 if len(itr.points) == 0 { 9003 var err error 9004 itr.points, err = itr.reduce() 9005 if len(itr.points) == 0 { 9006 return nil, err 9007 } 9008 } 9009 9010 // Pop next point off the stack. 9011 p := &itr.points[len(itr.points)-1] 9012 itr.points = itr.points[:len(itr.points)-1] 9013 return p, nil 9014} 9015 9016// stringReduceFloatPoint stores the reduced data for a name/tag combination. 9017type stringReduceFloatPoint struct { 9018 Name string 9019 Tags Tags 9020 Aggregator StringPointAggregator 9021 Emitter FloatPointEmitter 9022} 9023 9024// reduce executes fn once for every point in the next window. 9025// The previous value for the dimension is passed to fn. 9026func (itr *stringReduceFloatIterator) reduce() ([]FloatPoint, error) { 9027 // Calculate next window. 9028 var ( 9029 startTime, endTime int64 9030 window struct { 9031 name string 9032 tags string 9033 } 9034 ) 9035 for { 9036 p, err := itr.input.Next() 9037 if err != nil || p == nil { 9038 return nil, err 9039 } else if p.Nil { 9040 continue 9041 } 9042 9043 // Unread the point so it can be processed. 9044 itr.input.unread(p) 9045 startTime, endTime = itr.opt.Window(p.Time) 9046 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 9047 break 9048 } 9049 9050 // Create points by tags. 9051 m := make(map[string]*stringReduceFloatPoint) 9052 for { 9053 // Read next point. 9054 curr, err := itr.input.NextInWindow(startTime, endTime) 9055 if err != nil { 9056 return nil, err 9057 } else if curr == nil { 9058 break 9059 } else if curr.Nil { 9060 continue 9061 } else if curr.Name != window.name { 9062 itr.input.unread(curr) 9063 break 9064 } 9065 9066 // Ensure this point is within the same final window. 9067 if curr.Name != window.name { 9068 itr.input.unread(curr) 9069 break 9070 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 9071 itr.input.unread(curr) 9072 break 9073 } 9074 9075 // Retrieve the tags on this point for this level of the query. 9076 // This may be different than the bucket dimensions. 9077 tags := curr.Tags.Subset(itr.dims) 9078 id := tags.ID() 9079 9080 // Retrieve the aggregator for this name/tag combination or create one. 9081 rp := m[id] 9082 if rp == nil { 9083 aggregator, emitter := itr.create() 9084 rp = &stringReduceFloatPoint{ 9085 Name: curr.Name, 9086 Tags: tags, 9087 Aggregator: aggregator, 9088 Emitter: emitter, 9089 } 9090 m[id] = rp 9091 } 9092 rp.Aggregator.AggregateString(curr) 9093 } 9094 9095 keys := make([]string, 0, len(m)) 9096 for k := range m { 9097 keys = append(keys, k) 9098 } 9099 9100 // Reverse sort points by name & tag. 9101 // This ensures a consistent order of output. 9102 if len(keys) > 0 { 9103 var sorted sort.Interface = sort.StringSlice(keys) 9104 if itr.opt.Ascending { 9105 sorted = sort.Reverse(sorted) 9106 } 9107 sort.Sort(sorted) 9108 } 9109 9110 // Assume the points are already sorted until proven otherwise. 9111 sortedByTime := true 9112 // Emit the points for each name & tag combination. 9113 a := make([]FloatPoint, 0, len(m)) 9114 for _, k := range keys { 9115 rp := m[k] 9116 points := rp.Emitter.Emit() 9117 for i := len(points) - 1; i >= 0; i-- { 9118 points[i].Name = rp.Name 9119 if !itr.keepTags { 9120 points[i].Tags = rp.Tags 9121 } 9122 // Set the points time to the interval time if the reducer didn't provide one. 9123 if points[i].Time == ZeroTime { 9124 points[i].Time = startTime 9125 } else { 9126 sortedByTime = false 9127 } 9128 a = append(a, points[i]) 9129 } 9130 } 9131 // Points may be out of order. Perform a stable sort by time if requested. 9132 if !sortedByTime && itr.opt.Ordered { 9133 var sorted sort.Interface = floatPointsByTime(a) 9134 if itr.opt.Ascending { 9135 sorted = sort.Reverse(sorted) 9136 } 9137 sort.Stable(sorted) 9138 } 9139 return a, nil 9140} 9141 9142// stringStreamFloatIterator streams inputs into the iterator and emits points gradually. 9143type stringStreamFloatIterator struct { 9144 input *bufStringIterator 9145 create func() (StringPointAggregator, FloatPointEmitter) 9146 dims []string 9147 opt IteratorOptions 9148 m map[string]*stringReduceFloatPoint 9149 points []FloatPoint 9150} 9151 9152// newStringStreamFloatIterator returns a new instance of stringStreamFloatIterator. 9153func newStringStreamFloatIterator(input StringIterator, createFn func() (StringPointAggregator, FloatPointEmitter), opt IteratorOptions) *stringStreamFloatIterator { 9154 return &stringStreamFloatIterator{ 9155 input: newBufStringIterator(input), 9156 create: createFn, 9157 dims: opt.GetDimensions(), 9158 opt: opt, 9159 m: make(map[string]*stringReduceFloatPoint), 9160 } 9161} 9162 9163// Stats returns stats from the input iterator. 9164func (itr *stringStreamFloatIterator) Stats() IteratorStats { return itr.input.Stats() } 9165 9166// Close closes the iterator and all child iterators. 9167func (itr *stringStreamFloatIterator) Close() error { return itr.input.Close() } 9168 9169// Next returns the next value for the stream iterator. 9170func (itr *stringStreamFloatIterator) Next() (*FloatPoint, error) { 9171 // Calculate next window if we have no more points. 9172 if len(itr.points) == 0 { 9173 var err error 9174 itr.points, err = itr.reduce() 9175 if len(itr.points) == 0 { 9176 return nil, err 9177 } 9178 } 9179 9180 // Pop next point off the stack. 9181 p := &itr.points[len(itr.points)-1] 9182 itr.points = itr.points[:len(itr.points)-1] 9183 return p, nil 9184} 9185 9186// reduce creates and manages aggregators for every point from the input. 9187// After aggregating a point, it always tries to emit a value using the emitter. 9188func (itr *stringStreamFloatIterator) reduce() ([]FloatPoint, error) { 9189 // We have already read all of the input points. 9190 if itr.m == nil { 9191 return nil, nil 9192 } 9193 9194 for { 9195 // Read next point. 9196 curr, err := itr.input.Next() 9197 if err != nil { 9198 return nil, err 9199 } else if curr == nil { 9200 // Close all of the aggregators to flush any remaining points to emit. 9201 var points []FloatPoint 9202 for _, rp := range itr.m { 9203 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 9204 if err := aggregator.Close(); err != nil { 9205 return nil, err 9206 } 9207 9208 pts := rp.Emitter.Emit() 9209 if len(pts) == 0 { 9210 continue 9211 } 9212 9213 for i := range pts { 9214 pts[i].Name = rp.Name 9215 pts[i].Tags = rp.Tags 9216 } 9217 points = append(points, pts...) 9218 } 9219 } 9220 9221 // Eliminate the aggregators and emitters. 9222 itr.m = nil 9223 return points, nil 9224 } else if curr.Nil { 9225 continue 9226 } 9227 tags := curr.Tags.Subset(itr.dims) 9228 9229 id := curr.Name 9230 if len(tags.m) > 0 { 9231 id += "\x00" + tags.ID() 9232 } 9233 9234 // Retrieve the aggregator for this name/tag combination or create one. 9235 rp := itr.m[id] 9236 if rp == nil { 9237 aggregator, emitter := itr.create() 9238 rp = &stringReduceFloatPoint{ 9239 Name: curr.Name, 9240 Tags: tags, 9241 Aggregator: aggregator, 9242 Emitter: emitter, 9243 } 9244 itr.m[id] = rp 9245 } 9246 rp.Aggregator.AggregateString(curr) 9247 9248 // Attempt to emit points from the aggregator. 9249 points := rp.Emitter.Emit() 9250 if len(points) == 0 { 9251 continue 9252 } 9253 9254 for i := range points { 9255 points[i].Name = rp.Name 9256 points[i].Tags = rp.Tags 9257 } 9258 return points, nil 9259 } 9260} 9261 9262// stringReduceIntegerIterator executes a reducer for every interval and buffers the result. 9263type stringReduceIntegerIterator struct { 9264 input *bufStringIterator 9265 create func() (StringPointAggregator, IntegerPointEmitter) 9266 dims []string 9267 opt IteratorOptions 9268 points []IntegerPoint 9269 keepTags bool 9270} 9271 9272func newStringReduceIntegerIterator(input StringIterator, opt IteratorOptions, createFn func() (StringPointAggregator, IntegerPointEmitter)) *stringReduceIntegerIterator { 9273 return &stringReduceIntegerIterator{ 9274 input: newBufStringIterator(input), 9275 create: createFn, 9276 dims: opt.GetDimensions(), 9277 opt: opt, 9278 } 9279} 9280 9281// Stats returns stats from the input iterator. 9282func (itr *stringReduceIntegerIterator) Stats() IteratorStats { return itr.input.Stats() } 9283 9284// Close closes the iterator and all child iterators. 9285func (itr *stringReduceIntegerIterator) Close() error { return itr.input.Close() } 9286 9287// Next returns the minimum value for the next available interval. 9288func (itr *stringReduceIntegerIterator) Next() (*IntegerPoint, error) { 9289 // Calculate next window if we have no more points. 9290 if len(itr.points) == 0 { 9291 var err error 9292 itr.points, err = itr.reduce() 9293 if len(itr.points) == 0 { 9294 return nil, err 9295 } 9296 } 9297 9298 // Pop next point off the stack. 9299 p := &itr.points[len(itr.points)-1] 9300 itr.points = itr.points[:len(itr.points)-1] 9301 return p, nil 9302} 9303 9304// stringReduceIntegerPoint stores the reduced data for a name/tag combination. 9305type stringReduceIntegerPoint struct { 9306 Name string 9307 Tags Tags 9308 Aggregator StringPointAggregator 9309 Emitter IntegerPointEmitter 9310} 9311 9312// reduce executes fn once for every point in the next window. 9313// The previous value for the dimension is passed to fn. 9314func (itr *stringReduceIntegerIterator) reduce() ([]IntegerPoint, error) { 9315 // Calculate next window. 9316 var ( 9317 startTime, endTime int64 9318 window struct { 9319 name string 9320 tags string 9321 } 9322 ) 9323 for { 9324 p, err := itr.input.Next() 9325 if err != nil || p == nil { 9326 return nil, err 9327 } else if p.Nil { 9328 continue 9329 } 9330 9331 // Unread the point so it can be processed. 9332 itr.input.unread(p) 9333 startTime, endTime = itr.opt.Window(p.Time) 9334 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 9335 break 9336 } 9337 9338 // Create points by tags. 9339 m := make(map[string]*stringReduceIntegerPoint) 9340 for { 9341 // Read next point. 9342 curr, err := itr.input.NextInWindow(startTime, endTime) 9343 if err != nil { 9344 return nil, err 9345 } else if curr == nil { 9346 break 9347 } else if curr.Nil { 9348 continue 9349 } else if curr.Name != window.name { 9350 itr.input.unread(curr) 9351 break 9352 } 9353 9354 // Ensure this point is within the same final window. 9355 if curr.Name != window.name { 9356 itr.input.unread(curr) 9357 break 9358 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 9359 itr.input.unread(curr) 9360 break 9361 } 9362 9363 // Retrieve the tags on this point for this level of the query. 9364 // This may be different than the bucket dimensions. 9365 tags := curr.Tags.Subset(itr.dims) 9366 id := tags.ID() 9367 9368 // Retrieve the aggregator for this name/tag combination or create one. 9369 rp := m[id] 9370 if rp == nil { 9371 aggregator, emitter := itr.create() 9372 rp = &stringReduceIntegerPoint{ 9373 Name: curr.Name, 9374 Tags: tags, 9375 Aggregator: aggregator, 9376 Emitter: emitter, 9377 } 9378 m[id] = rp 9379 } 9380 rp.Aggregator.AggregateString(curr) 9381 } 9382 9383 keys := make([]string, 0, len(m)) 9384 for k := range m { 9385 keys = append(keys, k) 9386 } 9387 9388 // Reverse sort points by name & tag. 9389 // This ensures a consistent order of output. 9390 if len(keys) > 0 { 9391 var sorted sort.Interface = sort.StringSlice(keys) 9392 if itr.opt.Ascending { 9393 sorted = sort.Reverse(sorted) 9394 } 9395 sort.Sort(sorted) 9396 } 9397 9398 // Assume the points are already sorted until proven otherwise. 9399 sortedByTime := true 9400 // Emit the points for each name & tag combination. 9401 a := make([]IntegerPoint, 0, len(m)) 9402 for _, k := range keys { 9403 rp := m[k] 9404 points := rp.Emitter.Emit() 9405 for i := len(points) - 1; i >= 0; i-- { 9406 points[i].Name = rp.Name 9407 if !itr.keepTags { 9408 points[i].Tags = rp.Tags 9409 } 9410 // Set the points time to the interval time if the reducer didn't provide one. 9411 if points[i].Time == ZeroTime { 9412 points[i].Time = startTime 9413 } else { 9414 sortedByTime = false 9415 } 9416 a = append(a, points[i]) 9417 } 9418 } 9419 // Points may be out of order. Perform a stable sort by time if requested. 9420 if !sortedByTime && itr.opt.Ordered { 9421 var sorted sort.Interface = integerPointsByTime(a) 9422 if itr.opt.Ascending { 9423 sorted = sort.Reverse(sorted) 9424 } 9425 sort.Stable(sorted) 9426 } 9427 return a, nil 9428} 9429 9430// stringStreamIntegerIterator streams inputs into the iterator and emits points gradually. 9431type stringStreamIntegerIterator struct { 9432 input *bufStringIterator 9433 create func() (StringPointAggregator, IntegerPointEmitter) 9434 dims []string 9435 opt IteratorOptions 9436 m map[string]*stringReduceIntegerPoint 9437 points []IntegerPoint 9438} 9439 9440// newStringStreamIntegerIterator returns a new instance of stringStreamIntegerIterator. 9441func newStringStreamIntegerIterator(input StringIterator, createFn func() (StringPointAggregator, IntegerPointEmitter), opt IteratorOptions) *stringStreamIntegerIterator { 9442 return &stringStreamIntegerIterator{ 9443 input: newBufStringIterator(input), 9444 create: createFn, 9445 dims: opt.GetDimensions(), 9446 opt: opt, 9447 m: make(map[string]*stringReduceIntegerPoint), 9448 } 9449} 9450 9451// Stats returns stats from the input iterator. 9452func (itr *stringStreamIntegerIterator) Stats() IteratorStats { return itr.input.Stats() } 9453 9454// Close closes the iterator and all child iterators. 9455func (itr *stringStreamIntegerIterator) Close() error { return itr.input.Close() } 9456 9457// Next returns the next value for the stream iterator. 9458func (itr *stringStreamIntegerIterator) Next() (*IntegerPoint, error) { 9459 // Calculate next window if we have no more points. 9460 if len(itr.points) == 0 { 9461 var err error 9462 itr.points, err = itr.reduce() 9463 if len(itr.points) == 0 { 9464 return nil, err 9465 } 9466 } 9467 9468 // Pop next point off the stack. 9469 p := &itr.points[len(itr.points)-1] 9470 itr.points = itr.points[:len(itr.points)-1] 9471 return p, nil 9472} 9473 9474// reduce creates and manages aggregators for every point from the input. 9475// After aggregating a point, it always tries to emit a value using the emitter. 9476func (itr *stringStreamIntegerIterator) reduce() ([]IntegerPoint, error) { 9477 // We have already read all of the input points. 9478 if itr.m == nil { 9479 return nil, nil 9480 } 9481 9482 for { 9483 // Read next point. 9484 curr, err := itr.input.Next() 9485 if err != nil { 9486 return nil, err 9487 } else if curr == nil { 9488 // Close all of the aggregators to flush any remaining points to emit. 9489 var points []IntegerPoint 9490 for _, rp := range itr.m { 9491 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 9492 if err := aggregator.Close(); err != nil { 9493 return nil, err 9494 } 9495 9496 pts := rp.Emitter.Emit() 9497 if len(pts) == 0 { 9498 continue 9499 } 9500 9501 for i := range pts { 9502 pts[i].Name = rp.Name 9503 pts[i].Tags = rp.Tags 9504 } 9505 points = append(points, pts...) 9506 } 9507 } 9508 9509 // Eliminate the aggregators and emitters. 9510 itr.m = nil 9511 return points, nil 9512 } else if curr.Nil { 9513 continue 9514 } 9515 tags := curr.Tags.Subset(itr.dims) 9516 9517 id := curr.Name 9518 if len(tags.m) > 0 { 9519 id += "\x00" + tags.ID() 9520 } 9521 9522 // Retrieve the aggregator for this name/tag combination or create one. 9523 rp := itr.m[id] 9524 if rp == nil { 9525 aggregator, emitter := itr.create() 9526 rp = &stringReduceIntegerPoint{ 9527 Name: curr.Name, 9528 Tags: tags, 9529 Aggregator: aggregator, 9530 Emitter: emitter, 9531 } 9532 itr.m[id] = rp 9533 } 9534 rp.Aggregator.AggregateString(curr) 9535 9536 // Attempt to emit points from the aggregator. 9537 points := rp.Emitter.Emit() 9538 if len(points) == 0 { 9539 continue 9540 } 9541 9542 for i := range points { 9543 points[i].Name = rp.Name 9544 points[i].Tags = rp.Tags 9545 } 9546 return points, nil 9547 } 9548} 9549 9550// stringReduceUnsignedIterator executes a reducer for every interval and buffers the result. 9551type stringReduceUnsignedIterator struct { 9552 input *bufStringIterator 9553 create func() (StringPointAggregator, UnsignedPointEmitter) 9554 dims []string 9555 opt IteratorOptions 9556 points []UnsignedPoint 9557 keepTags bool 9558} 9559 9560func newStringReduceUnsignedIterator(input StringIterator, opt IteratorOptions, createFn func() (StringPointAggregator, UnsignedPointEmitter)) *stringReduceUnsignedIterator { 9561 return &stringReduceUnsignedIterator{ 9562 input: newBufStringIterator(input), 9563 create: createFn, 9564 dims: opt.GetDimensions(), 9565 opt: opt, 9566 } 9567} 9568 9569// Stats returns stats from the input iterator. 9570func (itr *stringReduceUnsignedIterator) Stats() IteratorStats { return itr.input.Stats() } 9571 9572// Close closes the iterator and all child iterators. 9573func (itr *stringReduceUnsignedIterator) Close() error { return itr.input.Close() } 9574 9575// Next returns the minimum value for the next available interval. 9576func (itr *stringReduceUnsignedIterator) Next() (*UnsignedPoint, error) { 9577 // Calculate next window if we have no more points. 9578 if len(itr.points) == 0 { 9579 var err error 9580 itr.points, err = itr.reduce() 9581 if len(itr.points) == 0 { 9582 return nil, err 9583 } 9584 } 9585 9586 // Pop next point off the stack. 9587 p := &itr.points[len(itr.points)-1] 9588 itr.points = itr.points[:len(itr.points)-1] 9589 return p, nil 9590} 9591 9592// stringReduceUnsignedPoint stores the reduced data for a name/tag combination. 9593type stringReduceUnsignedPoint struct { 9594 Name string 9595 Tags Tags 9596 Aggregator StringPointAggregator 9597 Emitter UnsignedPointEmitter 9598} 9599 9600// reduce executes fn once for every point in the next window. 9601// The previous value for the dimension is passed to fn. 9602func (itr *stringReduceUnsignedIterator) reduce() ([]UnsignedPoint, error) { 9603 // Calculate next window. 9604 var ( 9605 startTime, endTime int64 9606 window struct { 9607 name string 9608 tags string 9609 } 9610 ) 9611 for { 9612 p, err := itr.input.Next() 9613 if err != nil || p == nil { 9614 return nil, err 9615 } else if p.Nil { 9616 continue 9617 } 9618 9619 // Unread the point so it can be processed. 9620 itr.input.unread(p) 9621 startTime, endTime = itr.opt.Window(p.Time) 9622 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 9623 break 9624 } 9625 9626 // Create points by tags. 9627 m := make(map[string]*stringReduceUnsignedPoint) 9628 for { 9629 // Read next point. 9630 curr, err := itr.input.NextInWindow(startTime, endTime) 9631 if err != nil { 9632 return nil, err 9633 } else if curr == nil { 9634 break 9635 } else if curr.Nil { 9636 continue 9637 } else if curr.Name != window.name { 9638 itr.input.unread(curr) 9639 break 9640 } 9641 9642 // Ensure this point is within the same final window. 9643 if curr.Name != window.name { 9644 itr.input.unread(curr) 9645 break 9646 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 9647 itr.input.unread(curr) 9648 break 9649 } 9650 9651 // Retrieve the tags on this point for this level of the query. 9652 // This may be different than the bucket dimensions. 9653 tags := curr.Tags.Subset(itr.dims) 9654 id := tags.ID() 9655 9656 // Retrieve the aggregator for this name/tag combination or create one. 9657 rp := m[id] 9658 if rp == nil { 9659 aggregator, emitter := itr.create() 9660 rp = &stringReduceUnsignedPoint{ 9661 Name: curr.Name, 9662 Tags: tags, 9663 Aggregator: aggregator, 9664 Emitter: emitter, 9665 } 9666 m[id] = rp 9667 } 9668 rp.Aggregator.AggregateString(curr) 9669 } 9670 9671 keys := make([]string, 0, len(m)) 9672 for k := range m { 9673 keys = append(keys, k) 9674 } 9675 9676 // Reverse sort points by name & tag. 9677 // This ensures a consistent order of output. 9678 if len(keys) > 0 { 9679 var sorted sort.Interface = sort.StringSlice(keys) 9680 if itr.opt.Ascending { 9681 sorted = sort.Reverse(sorted) 9682 } 9683 sort.Sort(sorted) 9684 } 9685 9686 // Assume the points are already sorted until proven otherwise. 9687 sortedByTime := true 9688 // Emit the points for each name & tag combination. 9689 a := make([]UnsignedPoint, 0, len(m)) 9690 for _, k := range keys { 9691 rp := m[k] 9692 points := rp.Emitter.Emit() 9693 for i := len(points) - 1; i >= 0; i-- { 9694 points[i].Name = rp.Name 9695 if !itr.keepTags { 9696 points[i].Tags = rp.Tags 9697 } 9698 // Set the points time to the interval time if the reducer didn't provide one. 9699 if points[i].Time == ZeroTime { 9700 points[i].Time = startTime 9701 } else { 9702 sortedByTime = false 9703 } 9704 a = append(a, points[i]) 9705 } 9706 } 9707 // Points may be out of order. Perform a stable sort by time if requested. 9708 if !sortedByTime && itr.opt.Ordered { 9709 var sorted sort.Interface = unsignedPointsByTime(a) 9710 if itr.opt.Ascending { 9711 sorted = sort.Reverse(sorted) 9712 } 9713 sort.Stable(sorted) 9714 } 9715 return a, nil 9716} 9717 9718// stringStreamUnsignedIterator streams inputs into the iterator and emits points gradually. 9719type stringStreamUnsignedIterator struct { 9720 input *bufStringIterator 9721 create func() (StringPointAggregator, UnsignedPointEmitter) 9722 dims []string 9723 opt IteratorOptions 9724 m map[string]*stringReduceUnsignedPoint 9725 points []UnsignedPoint 9726} 9727 9728// newStringStreamUnsignedIterator returns a new instance of stringStreamUnsignedIterator. 9729func newStringStreamUnsignedIterator(input StringIterator, createFn func() (StringPointAggregator, UnsignedPointEmitter), opt IteratorOptions) *stringStreamUnsignedIterator { 9730 return &stringStreamUnsignedIterator{ 9731 input: newBufStringIterator(input), 9732 create: createFn, 9733 dims: opt.GetDimensions(), 9734 opt: opt, 9735 m: make(map[string]*stringReduceUnsignedPoint), 9736 } 9737} 9738 9739// Stats returns stats from the input iterator. 9740func (itr *stringStreamUnsignedIterator) Stats() IteratorStats { return itr.input.Stats() } 9741 9742// Close closes the iterator and all child iterators. 9743func (itr *stringStreamUnsignedIterator) Close() error { return itr.input.Close() } 9744 9745// Next returns the next value for the stream iterator. 9746func (itr *stringStreamUnsignedIterator) Next() (*UnsignedPoint, error) { 9747 // Calculate next window if we have no more points. 9748 if len(itr.points) == 0 { 9749 var err error 9750 itr.points, err = itr.reduce() 9751 if len(itr.points) == 0 { 9752 return nil, err 9753 } 9754 } 9755 9756 // Pop next point off the stack. 9757 p := &itr.points[len(itr.points)-1] 9758 itr.points = itr.points[:len(itr.points)-1] 9759 return p, nil 9760} 9761 9762// reduce creates and manages aggregators for every point from the input. 9763// After aggregating a point, it always tries to emit a value using the emitter. 9764func (itr *stringStreamUnsignedIterator) reduce() ([]UnsignedPoint, error) { 9765 // We have already read all of the input points. 9766 if itr.m == nil { 9767 return nil, nil 9768 } 9769 9770 for { 9771 // Read next point. 9772 curr, err := itr.input.Next() 9773 if err != nil { 9774 return nil, err 9775 } else if curr == nil { 9776 // Close all of the aggregators to flush any remaining points to emit. 9777 var points []UnsignedPoint 9778 for _, rp := range itr.m { 9779 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 9780 if err := aggregator.Close(); err != nil { 9781 return nil, err 9782 } 9783 9784 pts := rp.Emitter.Emit() 9785 if len(pts) == 0 { 9786 continue 9787 } 9788 9789 for i := range pts { 9790 pts[i].Name = rp.Name 9791 pts[i].Tags = rp.Tags 9792 } 9793 points = append(points, pts...) 9794 } 9795 } 9796 9797 // Eliminate the aggregators and emitters. 9798 itr.m = nil 9799 return points, nil 9800 } else if curr.Nil { 9801 continue 9802 } 9803 tags := curr.Tags.Subset(itr.dims) 9804 9805 id := curr.Name 9806 if len(tags.m) > 0 { 9807 id += "\x00" + tags.ID() 9808 } 9809 9810 // Retrieve the aggregator for this name/tag combination or create one. 9811 rp := itr.m[id] 9812 if rp == nil { 9813 aggregator, emitter := itr.create() 9814 rp = &stringReduceUnsignedPoint{ 9815 Name: curr.Name, 9816 Tags: tags, 9817 Aggregator: aggregator, 9818 Emitter: emitter, 9819 } 9820 itr.m[id] = rp 9821 } 9822 rp.Aggregator.AggregateString(curr) 9823 9824 // Attempt to emit points from the aggregator. 9825 points := rp.Emitter.Emit() 9826 if len(points) == 0 { 9827 continue 9828 } 9829 9830 for i := range points { 9831 points[i].Name = rp.Name 9832 points[i].Tags = rp.Tags 9833 } 9834 return points, nil 9835 } 9836} 9837 9838// stringReduceStringIterator executes a reducer for every interval and buffers the result. 9839type stringReduceStringIterator struct { 9840 input *bufStringIterator 9841 create func() (StringPointAggregator, StringPointEmitter) 9842 dims []string 9843 opt IteratorOptions 9844 points []StringPoint 9845 keepTags bool 9846} 9847 9848func newStringReduceStringIterator(input StringIterator, opt IteratorOptions, createFn func() (StringPointAggregator, StringPointEmitter)) *stringReduceStringIterator { 9849 return &stringReduceStringIterator{ 9850 input: newBufStringIterator(input), 9851 create: createFn, 9852 dims: opt.GetDimensions(), 9853 opt: opt, 9854 } 9855} 9856 9857// Stats returns stats from the input iterator. 9858func (itr *stringReduceStringIterator) Stats() IteratorStats { return itr.input.Stats() } 9859 9860// Close closes the iterator and all child iterators. 9861func (itr *stringReduceStringIterator) Close() error { return itr.input.Close() } 9862 9863// Next returns the minimum value for the next available interval. 9864func (itr *stringReduceStringIterator) Next() (*StringPoint, error) { 9865 // Calculate next window if we have no more points. 9866 if len(itr.points) == 0 { 9867 var err error 9868 itr.points, err = itr.reduce() 9869 if len(itr.points) == 0 { 9870 return nil, err 9871 } 9872 } 9873 9874 // Pop next point off the stack. 9875 p := &itr.points[len(itr.points)-1] 9876 itr.points = itr.points[:len(itr.points)-1] 9877 return p, nil 9878} 9879 9880// stringReduceStringPoint stores the reduced data for a name/tag combination. 9881type stringReduceStringPoint struct { 9882 Name string 9883 Tags Tags 9884 Aggregator StringPointAggregator 9885 Emitter StringPointEmitter 9886} 9887 9888// reduce executes fn once for every point in the next window. 9889// The previous value for the dimension is passed to fn. 9890func (itr *stringReduceStringIterator) reduce() ([]StringPoint, error) { 9891 // Calculate next window. 9892 var ( 9893 startTime, endTime int64 9894 window struct { 9895 name string 9896 tags string 9897 } 9898 ) 9899 for { 9900 p, err := itr.input.Next() 9901 if err != nil || p == nil { 9902 return nil, err 9903 } else if p.Nil { 9904 continue 9905 } 9906 9907 // Unread the point so it can be processed. 9908 itr.input.unread(p) 9909 startTime, endTime = itr.opt.Window(p.Time) 9910 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 9911 break 9912 } 9913 9914 // Create points by tags. 9915 m := make(map[string]*stringReduceStringPoint) 9916 for { 9917 // Read next point. 9918 curr, err := itr.input.NextInWindow(startTime, endTime) 9919 if err != nil { 9920 return nil, err 9921 } else if curr == nil { 9922 break 9923 } else if curr.Nil { 9924 continue 9925 } else if curr.Name != window.name { 9926 itr.input.unread(curr) 9927 break 9928 } 9929 9930 // Ensure this point is within the same final window. 9931 if curr.Name != window.name { 9932 itr.input.unread(curr) 9933 break 9934 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 9935 itr.input.unread(curr) 9936 break 9937 } 9938 9939 // Retrieve the tags on this point for this level of the query. 9940 // This may be different than the bucket dimensions. 9941 tags := curr.Tags.Subset(itr.dims) 9942 id := tags.ID() 9943 9944 // Retrieve the aggregator for this name/tag combination or create one. 9945 rp := m[id] 9946 if rp == nil { 9947 aggregator, emitter := itr.create() 9948 rp = &stringReduceStringPoint{ 9949 Name: curr.Name, 9950 Tags: tags, 9951 Aggregator: aggregator, 9952 Emitter: emitter, 9953 } 9954 m[id] = rp 9955 } 9956 rp.Aggregator.AggregateString(curr) 9957 } 9958 9959 keys := make([]string, 0, len(m)) 9960 for k := range m { 9961 keys = append(keys, k) 9962 } 9963 9964 // Reverse sort points by name & tag. 9965 // This ensures a consistent order of output. 9966 if len(keys) > 0 { 9967 var sorted sort.Interface = sort.StringSlice(keys) 9968 if itr.opt.Ascending { 9969 sorted = sort.Reverse(sorted) 9970 } 9971 sort.Sort(sorted) 9972 } 9973 9974 // Assume the points are already sorted until proven otherwise. 9975 sortedByTime := true 9976 // Emit the points for each name & tag combination. 9977 a := make([]StringPoint, 0, len(m)) 9978 for _, k := range keys { 9979 rp := m[k] 9980 points := rp.Emitter.Emit() 9981 for i := len(points) - 1; i >= 0; i-- { 9982 points[i].Name = rp.Name 9983 if !itr.keepTags { 9984 points[i].Tags = rp.Tags 9985 } 9986 // Set the points time to the interval time if the reducer didn't provide one. 9987 if points[i].Time == ZeroTime { 9988 points[i].Time = startTime 9989 } else { 9990 sortedByTime = false 9991 } 9992 a = append(a, points[i]) 9993 } 9994 } 9995 // Points may be out of order. Perform a stable sort by time if requested. 9996 if !sortedByTime && itr.opt.Ordered { 9997 var sorted sort.Interface = stringPointsByTime(a) 9998 if itr.opt.Ascending { 9999 sorted = sort.Reverse(sorted) 10000 } 10001 sort.Stable(sorted) 10002 } 10003 return a, nil 10004} 10005 10006// stringStreamStringIterator streams inputs into the iterator and emits points gradually. 10007type stringStreamStringIterator struct { 10008 input *bufStringIterator 10009 create func() (StringPointAggregator, StringPointEmitter) 10010 dims []string 10011 opt IteratorOptions 10012 m map[string]*stringReduceStringPoint 10013 points []StringPoint 10014} 10015 10016// newStringStreamStringIterator returns a new instance of stringStreamStringIterator. 10017func newStringStreamStringIterator(input StringIterator, createFn func() (StringPointAggregator, StringPointEmitter), opt IteratorOptions) *stringStreamStringIterator { 10018 return &stringStreamStringIterator{ 10019 input: newBufStringIterator(input), 10020 create: createFn, 10021 dims: opt.GetDimensions(), 10022 opt: opt, 10023 m: make(map[string]*stringReduceStringPoint), 10024 } 10025} 10026 10027// Stats returns stats from the input iterator. 10028func (itr *stringStreamStringIterator) Stats() IteratorStats { return itr.input.Stats() } 10029 10030// Close closes the iterator and all child iterators. 10031func (itr *stringStreamStringIterator) Close() error { return itr.input.Close() } 10032 10033// Next returns the next value for the stream iterator. 10034func (itr *stringStreamStringIterator) Next() (*StringPoint, error) { 10035 // Calculate next window if we have no more points. 10036 if len(itr.points) == 0 { 10037 var err error 10038 itr.points, err = itr.reduce() 10039 if len(itr.points) == 0 { 10040 return nil, err 10041 } 10042 } 10043 10044 // Pop next point off the stack. 10045 p := &itr.points[len(itr.points)-1] 10046 itr.points = itr.points[:len(itr.points)-1] 10047 return p, nil 10048} 10049 10050// reduce creates and manages aggregators for every point from the input. 10051// After aggregating a point, it always tries to emit a value using the emitter. 10052func (itr *stringStreamStringIterator) reduce() ([]StringPoint, error) { 10053 // We have already read all of the input points. 10054 if itr.m == nil { 10055 return nil, nil 10056 } 10057 10058 for { 10059 // Read next point. 10060 curr, err := itr.input.Next() 10061 if err != nil { 10062 return nil, err 10063 } else if curr == nil { 10064 // Close all of the aggregators to flush any remaining points to emit. 10065 var points []StringPoint 10066 for _, rp := range itr.m { 10067 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 10068 if err := aggregator.Close(); err != nil { 10069 return nil, err 10070 } 10071 10072 pts := rp.Emitter.Emit() 10073 if len(pts) == 0 { 10074 continue 10075 } 10076 10077 for i := range pts { 10078 pts[i].Name = rp.Name 10079 pts[i].Tags = rp.Tags 10080 } 10081 points = append(points, pts...) 10082 } 10083 } 10084 10085 // Eliminate the aggregators and emitters. 10086 itr.m = nil 10087 return points, nil 10088 } else if curr.Nil { 10089 continue 10090 } 10091 tags := curr.Tags.Subset(itr.dims) 10092 10093 id := curr.Name 10094 if len(tags.m) > 0 { 10095 id += "\x00" + tags.ID() 10096 } 10097 10098 // Retrieve the aggregator for this name/tag combination or create one. 10099 rp := itr.m[id] 10100 if rp == nil { 10101 aggregator, emitter := itr.create() 10102 rp = &stringReduceStringPoint{ 10103 Name: curr.Name, 10104 Tags: tags, 10105 Aggregator: aggregator, 10106 Emitter: emitter, 10107 } 10108 itr.m[id] = rp 10109 } 10110 rp.Aggregator.AggregateString(curr) 10111 10112 // Attempt to emit points from the aggregator. 10113 points := rp.Emitter.Emit() 10114 if len(points) == 0 { 10115 continue 10116 } 10117 10118 for i := range points { 10119 points[i].Name = rp.Name 10120 points[i].Tags = rp.Tags 10121 } 10122 return points, nil 10123 } 10124} 10125 10126// stringReduceBooleanIterator executes a reducer for every interval and buffers the result. 10127type stringReduceBooleanIterator struct { 10128 input *bufStringIterator 10129 create func() (StringPointAggregator, BooleanPointEmitter) 10130 dims []string 10131 opt IteratorOptions 10132 points []BooleanPoint 10133 keepTags bool 10134} 10135 10136func newStringReduceBooleanIterator(input StringIterator, opt IteratorOptions, createFn func() (StringPointAggregator, BooleanPointEmitter)) *stringReduceBooleanIterator { 10137 return &stringReduceBooleanIterator{ 10138 input: newBufStringIterator(input), 10139 create: createFn, 10140 dims: opt.GetDimensions(), 10141 opt: opt, 10142 } 10143} 10144 10145// Stats returns stats from the input iterator. 10146func (itr *stringReduceBooleanIterator) Stats() IteratorStats { return itr.input.Stats() } 10147 10148// Close closes the iterator and all child iterators. 10149func (itr *stringReduceBooleanIterator) Close() error { return itr.input.Close() } 10150 10151// Next returns the minimum value for the next available interval. 10152func (itr *stringReduceBooleanIterator) Next() (*BooleanPoint, error) { 10153 // Calculate next window if we have no more points. 10154 if len(itr.points) == 0 { 10155 var err error 10156 itr.points, err = itr.reduce() 10157 if len(itr.points) == 0 { 10158 return nil, err 10159 } 10160 } 10161 10162 // Pop next point off the stack. 10163 p := &itr.points[len(itr.points)-1] 10164 itr.points = itr.points[:len(itr.points)-1] 10165 return p, nil 10166} 10167 10168// stringReduceBooleanPoint stores the reduced data for a name/tag combination. 10169type stringReduceBooleanPoint struct { 10170 Name string 10171 Tags Tags 10172 Aggregator StringPointAggregator 10173 Emitter BooleanPointEmitter 10174} 10175 10176// reduce executes fn once for every point in the next window. 10177// The previous value for the dimension is passed to fn. 10178func (itr *stringReduceBooleanIterator) reduce() ([]BooleanPoint, error) { 10179 // Calculate next window. 10180 var ( 10181 startTime, endTime int64 10182 window struct { 10183 name string 10184 tags string 10185 } 10186 ) 10187 for { 10188 p, err := itr.input.Next() 10189 if err != nil || p == nil { 10190 return nil, err 10191 } else if p.Nil { 10192 continue 10193 } 10194 10195 // Unread the point so it can be processed. 10196 itr.input.unread(p) 10197 startTime, endTime = itr.opt.Window(p.Time) 10198 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 10199 break 10200 } 10201 10202 // Create points by tags. 10203 m := make(map[string]*stringReduceBooleanPoint) 10204 for { 10205 // Read next point. 10206 curr, err := itr.input.NextInWindow(startTime, endTime) 10207 if err != nil { 10208 return nil, err 10209 } else if curr == nil { 10210 break 10211 } else if curr.Nil { 10212 continue 10213 } else if curr.Name != window.name { 10214 itr.input.unread(curr) 10215 break 10216 } 10217 10218 // Ensure this point is within the same final window. 10219 if curr.Name != window.name { 10220 itr.input.unread(curr) 10221 break 10222 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 10223 itr.input.unread(curr) 10224 break 10225 } 10226 10227 // Retrieve the tags on this point for this level of the query. 10228 // This may be different than the bucket dimensions. 10229 tags := curr.Tags.Subset(itr.dims) 10230 id := tags.ID() 10231 10232 // Retrieve the aggregator for this name/tag combination or create one. 10233 rp := m[id] 10234 if rp == nil { 10235 aggregator, emitter := itr.create() 10236 rp = &stringReduceBooleanPoint{ 10237 Name: curr.Name, 10238 Tags: tags, 10239 Aggregator: aggregator, 10240 Emitter: emitter, 10241 } 10242 m[id] = rp 10243 } 10244 rp.Aggregator.AggregateString(curr) 10245 } 10246 10247 keys := make([]string, 0, len(m)) 10248 for k := range m { 10249 keys = append(keys, k) 10250 } 10251 10252 // Reverse sort points by name & tag. 10253 // This ensures a consistent order of output. 10254 if len(keys) > 0 { 10255 var sorted sort.Interface = sort.StringSlice(keys) 10256 if itr.opt.Ascending { 10257 sorted = sort.Reverse(sorted) 10258 } 10259 sort.Sort(sorted) 10260 } 10261 10262 // Assume the points are already sorted until proven otherwise. 10263 sortedByTime := true 10264 // Emit the points for each name & tag combination. 10265 a := make([]BooleanPoint, 0, len(m)) 10266 for _, k := range keys { 10267 rp := m[k] 10268 points := rp.Emitter.Emit() 10269 for i := len(points) - 1; i >= 0; i-- { 10270 points[i].Name = rp.Name 10271 if !itr.keepTags { 10272 points[i].Tags = rp.Tags 10273 } 10274 // Set the points time to the interval time if the reducer didn't provide one. 10275 if points[i].Time == ZeroTime { 10276 points[i].Time = startTime 10277 } else { 10278 sortedByTime = false 10279 } 10280 a = append(a, points[i]) 10281 } 10282 } 10283 // Points may be out of order. Perform a stable sort by time if requested. 10284 if !sortedByTime && itr.opt.Ordered { 10285 var sorted sort.Interface = booleanPointsByTime(a) 10286 if itr.opt.Ascending { 10287 sorted = sort.Reverse(sorted) 10288 } 10289 sort.Stable(sorted) 10290 } 10291 return a, nil 10292} 10293 10294// stringStreamBooleanIterator streams inputs into the iterator and emits points gradually. 10295type stringStreamBooleanIterator struct { 10296 input *bufStringIterator 10297 create func() (StringPointAggregator, BooleanPointEmitter) 10298 dims []string 10299 opt IteratorOptions 10300 m map[string]*stringReduceBooleanPoint 10301 points []BooleanPoint 10302} 10303 10304// newStringStreamBooleanIterator returns a new instance of stringStreamBooleanIterator. 10305func newStringStreamBooleanIterator(input StringIterator, createFn func() (StringPointAggregator, BooleanPointEmitter), opt IteratorOptions) *stringStreamBooleanIterator { 10306 return &stringStreamBooleanIterator{ 10307 input: newBufStringIterator(input), 10308 create: createFn, 10309 dims: opt.GetDimensions(), 10310 opt: opt, 10311 m: make(map[string]*stringReduceBooleanPoint), 10312 } 10313} 10314 10315// Stats returns stats from the input iterator. 10316func (itr *stringStreamBooleanIterator) Stats() IteratorStats { return itr.input.Stats() } 10317 10318// Close closes the iterator and all child iterators. 10319func (itr *stringStreamBooleanIterator) Close() error { return itr.input.Close() } 10320 10321// Next returns the next value for the stream iterator. 10322func (itr *stringStreamBooleanIterator) Next() (*BooleanPoint, error) { 10323 // Calculate next window if we have no more points. 10324 if len(itr.points) == 0 { 10325 var err error 10326 itr.points, err = itr.reduce() 10327 if len(itr.points) == 0 { 10328 return nil, err 10329 } 10330 } 10331 10332 // Pop next point off the stack. 10333 p := &itr.points[len(itr.points)-1] 10334 itr.points = itr.points[:len(itr.points)-1] 10335 return p, nil 10336} 10337 10338// reduce creates and manages aggregators for every point from the input. 10339// After aggregating a point, it always tries to emit a value using the emitter. 10340func (itr *stringStreamBooleanIterator) reduce() ([]BooleanPoint, error) { 10341 // We have already read all of the input points. 10342 if itr.m == nil { 10343 return nil, nil 10344 } 10345 10346 for { 10347 // Read next point. 10348 curr, err := itr.input.Next() 10349 if err != nil { 10350 return nil, err 10351 } else if curr == nil { 10352 // Close all of the aggregators to flush any remaining points to emit. 10353 var points []BooleanPoint 10354 for _, rp := range itr.m { 10355 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 10356 if err := aggregator.Close(); err != nil { 10357 return nil, err 10358 } 10359 10360 pts := rp.Emitter.Emit() 10361 if len(pts) == 0 { 10362 continue 10363 } 10364 10365 for i := range pts { 10366 pts[i].Name = rp.Name 10367 pts[i].Tags = rp.Tags 10368 } 10369 points = append(points, pts...) 10370 } 10371 } 10372 10373 // Eliminate the aggregators and emitters. 10374 itr.m = nil 10375 return points, nil 10376 } else if curr.Nil { 10377 continue 10378 } 10379 tags := curr.Tags.Subset(itr.dims) 10380 10381 id := curr.Name 10382 if len(tags.m) > 0 { 10383 id += "\x00" + tags.ID() 10384 } 10385 10386 // Retrieve the aggregator for this name/tag combination or create one. 10387 rp := itr.m[id] 10388 if rp == nil { 10389 aggregator, emitter := itr.create() 10390 rp = &stringReduceBooleanPoint{ 10391 Name: curr.Name, 10392 Tags: tags, 10393 Aggregator: aggregator, 10394 Emitter: emitter, 10395 } 10396 itr.m[id] = rp 10397 } 10398 rp.Aggregator.AggregateString(curr) 10399 10400 // Attempt to emit points from the aggregator. 10401 points := rp.Emitter.Emit() 10402 if len(points) == 0 { 10403 continue 10404 } 10405 10406 for i := range points { 10407 points[i].Name = rp.Name 10408 points[i].Tags = rp.Tags 10409 } 10410 return points, nil 10411 } 10412} 10413 10414// stringDedupeIterator only outputs unique points. 10415// This differs from the DistinctIterator in that it compares all aux fields too. 10416// This iterator is relatively inefficient and should only be used on small 10417// datasets such as meta query results. 10418type stringDedupeIterator struct { 10419 input StringIterator 10420 m map[string]struct{} // lookup of points already sent 10421} 10422 10423type stringIteratorMapper struct { 10424 cur Cursor 10425 row Row 10426 driver IteratorMap // which iterator to use for the primary value, can be nil 10427 fields []IteratorMap // which iterator to use for an aux field 10428 point StringPoint 10429} 10430 10431func newStringIteratorMapper(cur Cursor, driver IteratorMap, fields []IteratorMap, opt IteratorOptions) *stringIteratorMapper { 10432 return &stringIteratorMapper{ 10433 cur: cur, 10434 driver: driver, 10435 fields: fields, 10436 point: StringPoint{ 10437 Aux: make([]interface{}, len(fields)), 10438 }, 10439 } 10440} 10441 10442func (itr *stringIteratorMapper) Next() (*StringPoint, error) { 10443 if !itr.cur.Scan(&itr.row) { 10444 if err := itr.cur.Err(); err != nil { 10445 return nil, err 10446 } 10447 return nil, nil 10448 } 10449 10450 itr.point.Time = itr.row.Time 10451 itr.point.Name = itr.row.Series.Name 10452 itr.point.Tags = itr.row.Series.Tags 10453 10454 if itr.driver != nil { 10455 if v := itr.driver.Value(&itr.row); v != nil { 10456 if v, ok := castToString(v); ok { 10457 itr.point.Value = v 10458 itr.point.Nil = false 10459 } else { 10460 itr.point.Value = "" 10461 itr.point.Nil = true 10462 } 10463 } else { 10464 itr.point.Value = "" 10465 itr.point.Nil = true 10466 } 10467 } 10468 for i, f := range itr.fields { 10469 itr.point.Aux[i] = f.Value(&itr.row) 10470 } 10471 return &itr.point, nil 10472} 10473 10474func (itr *stringIteratorMapper) Stats() IteratorStats { 10475 return itr.cur.Stats() 10476} 10477 10478func (itr *stringIteratorMapper) Close() error { 10479 return itr.cur.Close() 10480} 10481 10482type stringFilterIterator struct { 10483 input StringIterator 10484 cond influxql.Expr 10485 opt IteratorOptions 10486 m map[string]interface{} 10487} 10488 10489func newStringFilterIterator(input StringIterator, cond influxql.Expr, opt IteratorOptions) StringIterator { 10490 // Strip out time conditions from the WHERE clause. 10491 // TODO(jsternberg): This should really be done for us when creating the IteratorOptions struct. 10492 n := influxql.RewriteFunc(influxql.CloneExpr(cond), func(n influxql.Node) influxql.Node { 10493 switch n := n.(type) { 10494 case *influxql.BinaryExpr: 10495 if n.LHS.String() == "time" { 10496 return &influxql.BooleanLiteral{Val: true} 10497 } 10498 } 10499 return n 10500 }) 10501 10502 cond, _ = n.(influxql.Expr) 10503 if cond == nil { 10504 return input 10505 } else if n, ok := cond.(*influxql.BooleanLiteral); ok && n.Val { 10506 return input 10507 } 10508 10509 return &stringFilterIterator{ 10510 input: input, 10511 cond: cond, 10512 opt: opt, 10513 m: make(map[string]interface{}), 10514 } 10515} 10516 10517func (itr *stringFilterIterator) Stats() IteratorStats { return itr.input.Stats() } 10518func (itr *stringFilterIterator) Close() error { return itr.input.Close() } 10519 10520func (itr *stringFilterIterator) Next() (*StringPoint, error) { 10521 for { 10522 p, err := itr.input.Next() 10523 if err != nil || p == nil { 10524 return nil, err 10525 } 10526 10527 for i, ref := range itr.opt.Aux { 10528 itr.m[ref.Val] = p.Aux[i] 10529 } 10530 for k, v := range p.Tags.KeyValues() { 10531 itr.m[k] = v 10532 } 10533 10534 if !influxql.EvalBool(itr.cond, itr.m) { 10535 continue 10536 } 10537 return p, nil 10538 } 10539} 10540 10541type stringTagSubsetIterator struct { 10542 input StringIterator 10543 point StringPoint 10544 lastTags Tags 10545 dimensions []string 10546} 10547 10548func newStringTagSubsetIterator(input StringIterator, opt IteratorOptions) *stringTagSubsetIterator { 10549 return &stringTagSubsetIterator{ 10550 input: input, 10551 dimensions: opt.GetDimensions(), 10552 } 10553} 10554 10555func (itr *stringTagSubsetIterator) Next() (*StringPoint, error) { 10556 p, err := itr.input.Next() 10557 if err != nil { 10558 return nil, err 10559 } else if p == nil { 10560 return nil, nil 10561 } 10562 10563 itr.point.Name = p.Name 10564 if !p.Tags.Equal(itr.lastTags) { 10565 itr.point.Tags = p.Tags.Subset(itr.dimensions) 10566 itr.lastTags = p.Tags 10567 } 10568 itr.point.Time = p.Time 10569 itr.point.Value = p.Value 10570 itr.point.Aux = p.Aux 10571 itr.point.Aggregated = p.Aggregated 10572 itr.point.Nil = p.Nil 10573 return &itr.point, nil 10574} 10575 10576func (itr *stringTagSubsetIterator) Stats() IteratorStats { 10577 return itr.input.Stats() 10578} 10579 10580func (itr *stringTagSubsetIterator) Close() error { 10581 return itr.input.Close() 10582} 10583 10584// newStringDedupeIterator returns a new instance of stringDedupeIterator. 10585func newStringDedupeIterator(input StringIterator) *stringDedupeIterator { 10586 return &stringDedupeIterator{ 10587 input: input, 10588 m: make(map[string]struct{}), 10589 } 10590} 10591 10592// Stats returns stats from the input iterator. 10593func (itr *stringDedupeIterator) Stats() IteratorStats { return itr.input.Stats() } 10594 10595// Close closes the iterator and all child iterators. 10596func (itr *stringDedupeIterator) Close() error { return itr.input.Close() } 10597 10598// Next returns the next unique point from the input iterator. 10599func (itr *stringDedupeIterator) Next() (*StringPoint, error) { 10600 for { 10601 // Read next point. 10602 p, err := itr.input.Next() 10603 if p == nil || err != nil { 10604 return nil, err 10605 } 10606 10607 // Serialize to bytes to store in lookup. 10608 buf, err := proto.Marshal(encodeStringPoint(p)) 10609 if err != nil { 10610 return nil, err 10611 } 10612 10613 // If the point has already been output then move to the next point. 10614 if _, ok := itr.m[string(buf)]; ok { 10615 continue 10616 } 10617 10618 // Otherwise mark it as emitted and return point. 10619 itr.m[string(buf)] = struct{}{} 10620 return p, nil 10621 } 10622} 10623 10624// stringReaderIterator represents an iterator that streams from a reader. 10625type stringReaderIterator struct { 10626 r io.Reader 10627 dec *StringPointDecoder 10628} 10629 10630// newStringReaderIterator returns a new instance of stringReaderIterator. 10631func newStringReaderIterator(ctx context.Context, r io.Reader, stats IteratorStats) *stringReaderIterator { 10632 dec := NewStringPointDecoder(ctx, r) 10633 dec.stats = stats 10634 10635 return &stringReaderIterator{ 10636 r: r, 10637 dec: dec, 10638 } 10639} 10640 10641// Stats returns stats about points processed. 10642func (itr *stringReaderIterator) Stats() IteratorStats { return itr.dec.stats } 10643 10644// Close closes the underlying reader, if applicable. 10645func (itr *stringReaderIterator) Close() error { 10646 if r, ok := itr.r.(io.ReadCloser); ok { 10647 return r.Close() 10648 } 10649 return nil 10650} 10651 10652// Next returns the next point from the iterator. 10653func (itr *stringReaderIterator) Next() (*StringPoint, error) { 10654 // OPTIMIZE(benbjohnson): Reuse point on iterator. 10655 10656 // Unmarshal next point. 10657 p := &StringPoint{} 10658 if err := itr.dec.DecodeStringPoint(p); err == io.EOF { 10659 return nil, nil 10660 } else if err != nil { 10661 return nil, err 10662 } 10663 return p, nil 10664} 10665 10666// BooleanIterator represents a stream of boolean points. 10667type BooleanIterator interface { 10668 Iterator 10669 Next() (*BooleanPoint, error) 10670} 10671 10672// newBooleanIterators converts a slice of Iterator to a slice of BooleanIterator. 10673// Drop and closes any iterator in itrs that is not a BooleanIterator and cannot 10674// be cast to a BooleanIterator. 10675func newBooleanIterators(itrs []Iterator) []BooleanIterator { 10676 a := make([]BooleanIterator, 0, len(itrs)) 10677 for _, itr := range itrs { 10678 switch itr := itr.(type) { 10679 case BooleanIterator: 10680 a = append(a, itr) 10681 default: 10682 itr.Close() 10683 } 10684 } 10685 return a 10686} 10687 10688// bufBooleanIterator represents a buffered BooleanIterator. 10689type bufBooleanIterator struct { 10690 itr BooleanIterator 10691 buf *BooleanPoint 10692} 10693 10694// newBufBooleanIterator returns a buffered BooleanIterator. 10695func newBufBooleanIterator(itr BooleanIterator) *bufBooleanIterator { 10696 return &bufBooleanIterator{itr: itr} 10697} 10698 10699// Stats returns statistics from the input iterator. 10700func (itr *bufBooleanIterator) Stats() IteratorStats { return itr.itr.Stats() } 10701 10702// Close closes the underlying iterator. 10703func (itr *bufBooleanIterator) Close() error { return itr.itr.Close() } 10704 10705// peek returns the next point without removing it from the iterator. 10706func (itr *bufBooleanIterator) peek() (*BooleanPoint, error) { 10707 p, err := itr.Next() 10708 if err != nil { 10709 return nil, err 10710 } 10711 itr.unread(p) 10712 return p, nil 10713} 10714 10715// peekTime returns the time of the next point. 10716// Returns zero time if no more points available. 10717func (itr *bufBooleanIterator) peekTime() (int64, error) { 10718 p, err := itr.peek() 10719 if p == nil || err != nil { 10720 return ZeroTime, err 10721 } 10722 return p.Time, nil 10723} 10724 10725// Next returns the current buffer, if exists, or calls the underlying iterator. 10726func (itr *bufBooleanIterator) Next() (*BooleanPoint, error) { 10727 buf := itr.buf 10728 if buf != nil { 10729 itr.buf = nil 10730 return buf, nil 10731 } 10732 return itr.itr.Next() 10733} 10734 10735// NextInWindow returns the next value if it is between [startTime, endTime). 10736// If the next value is outside the range then it is moved to the buffer. 10737func (itr *bufBooleanIterator) NextInWindow(startTime, endTime int64) (*BooleanPoint, error) { 10738 v, err := itr.Next() 10739 if v == nil || err != nil { 10740 return nil, err 10741 } else if t := v.Time; t >= endTime || t < startTime { 10742 itr.unread(v) 10743 return nil, nil 10744 } 10745 return v, nil 10746} 10747 10748// unread sets v to the buffer. It is read on the next call to Next(). 10749func (itr *bufBooleanIterator) unread(v *BooleanPoint) { itr.buf = v } 10750 10751// booleanMergeIterator represents an iterator that combines multiple boolean iterators. 10752type booleanMergeIterator struct { 10753 inputs []BooleanIterator 10754 heap *booleanMergeHeap 10755 init bool 10756 10757 closed bool 10758 mu sync.RWMutex 10759 10760 // Current iterator and window. 10761 curr *booleanMergeHeapItem 10762 window struct { 10763 name string 10764 tags string 10765 startTime int64 10766 endTime int64 10767 } 10768} 10769 10770// newBooleanMergeIterator returns a new instance of booleanMergeIterator. 10771func newBooleanMergeIterator(inputs []BooleanIterator, opt IteratorOptions) *booleanMergeIterator { 10772 itr := &booleanMergeIterator{ 10773 inputs: inputs, 10774 heap: &booleanMergeHeap{ 10775 items: make([]*booleanMergeHeapItem, 0, len(inputs)), 10776 opt: opt, 10777 }, 10778 } 10779 10780 // Initialize heap items. 10781 for _, input := range inputs { 10782 // Wrap in buffer, ignore any inputs without anymore points. 10783 bufInput := newBufBooleanIterator(input) 10784 10785 // Append to the heap. 10786 itr.heap.items = append(itr.heap.items, &booleanMergeHeapItem{itr: bufInput}) 10787 } 10788 10789 return itr 10790} 10791 10792// Stats returns an aggregation of stats from the underlying iterators. 10793func (itr *booleanMergeIterator) Stats() IteratorStats { 10794 var stats IteratorStats 10795 for _, input := range itr.inputs { 10796 stats.Add(input.Stats()) 10797 } 10798 return stats 10799} 10800 10801// Close closes the underlying iterators. 10802func (itr *booleanMergeIterator) Close() error { 10803 itr.mu.Lock() 10804 defer itr.mu.Unlock() 10805 10806 for _, input := range itr.inputs { 10807 input.Close() 10808 } 10809 itr.curr = nil 10810 itr.inputs = nil 10811 itr.heap.items = nil 10812 itr.closed = true 10813 return nil 10814} 10815 10816// Next returns the next point from the iterator. 10817func (itr *booleanMergeIterator) Next() (*BooleanPoint, error) { 10818 itr.mu.RLock() 10819 defer itr.mu.RUnlock() 10820 if itr.closed { 10821 return nil, nil 10822 } 10823 10824 // Initialize the heap. This needs to be done lazily on the first call to this iterator 10825 // so that iterator initialization done through the Select() call returns quickly. 10826 // Queries can only be interrupted after the Select() call completes so any operations 10827 // done during iterator creation cannot be interrupted, which is why we do it here 10828 // instead so an interrupt can happen while initializing the heap. 10829 if !itr.init { 10830 items := itr.heap.items 10831 itr.heap.items = make([]*booleanMergeHeapItem, 0, len(items)) 10832 for _, item := range items { 10833 if p, err := item.itr.peek(); err != nil { 10834 return nil, err 10835 } else if p == nil { 10836 continue 10837 } 10838 itr.heap.items = append(itr.heap.items, item) 10839 } 10840 heap.Init(itr.heap) 10841 itr.init = true 10842 } 10843 10844 for { 10845 // Retrieve the next iterator if we don't have one. 10846 if itr.curr == nil { 10847 if len(itr.heap.items) == 0 { 10848 return nil, nil 10849 } 10850 itr.curr = heap.Pop(itr.heap).(*booleanMergeHeapItem) 10851 10852 // Read point and set current window. 10853 p, err := itr.curr.itr.Next() 10854 if err != nil { 10855 return nil, err 10856 } 10857 tags := p.Tags.Subset(itr.heap.opt.Dimensions) 10858 itr.window.name, itr.window.tags = p.Name, tags.ID() 10859 itr.window.startTime, itr.window.endTime = itr.heap.opt.Window(p.Time) 10860 return p, nil 10861 } 10862 10863 // Read the next point from the current iterator. 10864 p, err := itr.curr.itr.Next() 10865 if err != nil { 10866 return nil, err 10867 } 10868 10869 // If there are no more points then remove iterator from heap and find next. 10870 if p == nil { 10871 itr.curr = nil 10872 continue 10873 } 10874 10875 // Check if the point is inside of our current window. 10876 inWindow := true 10877 if window := itr.window; window.name != p.Name { 10878 inWindow = false 10879 } else if tags := p.Tags.Subset(itr.heap.opt.Dimensions); window.tags != tags.ID() { 10880 inWindow = false 10881 } else if opt := itr.heap.opt; opt.Ascending && p.Time >= window.endTime { 10882 inWindow = false 10883 } else if !opt.Ascending && p.Time < window.startTime { 10884 inWindow = false 10885 } 10886 10887 // If it's outside our window then push iterator back on the heap and find new iterator. 10888 if !inWindow { 10889 itr.curr.itr.unread(p) 10890 heap.Push(itr.heap, itr.curr) 10891 itr.curr = nil 10892 continue 10893 } 10894 10895 return p, nil 10896 } 10897} 10898 10899// booleanMergeHeap represents a heap of booleanMergeHeapItems. 10900// Items are sorted by their next window and then by name/tags. 10901type booleanMergeHeap struct { 10902 opt IteratorOptions 10903 items []*booleanMergeHeapItem 10904} 10905 10906func (h *booleanMergeHeap) Len() int { return len(h.items) } 10907func (h *booleanMergeHeap) Swap(i, j int) { h.items[i], h.items[j] = h.items[j], h.items[i] } 10908func (h *booleanMergeHeap) Less(i, j int) bool { 10909 x, err := h.items[i].itr.peek() 10910 if err != nil { 10911 return true 10912 } 10913 y, err := h.items[j].itr.peek() 10914 if err != nil { 10915 return false 10916 } 10917 10918 if h.opt.Ascending { 10919 if x.Name != y.Name { 10920 return x.Name < y.Name 10921 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); xTags.ID() != yTags.ID() { 10922 return xTags.ID() < yTags.ID() 10923 } 10924 } else { 10925 if x.Name != y.Name { 10926 return x.Name > y.Name 10927 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); xTags.ID() != yTags.ID() { 10928 return xTags.ID() > yTags.ID() 10929 } 10930 } 10931 10932 xt, _ := h.opt.Window(x.Time) 10933 yt, _ := h.opt.Window(y.Time) 10934 10935 if h.opt.Ascending { 10936 return xt < yt 10937 } 10938 return xt > yt 10939} 10940 10941func (h *booleanMergeHeap) Push(x interface{}) { 10942 h.items = append(h.items, x.(*booleanMergeHeapItem)) 10943} 10944 10945func (h *booleanMergeHeap) Pop() interface{} { 10946 old := h.items 10947 n := len(old) 10948 item := old[n-1] 10949 h.items = old[0 : n-1] 10950 return item 10951} 10952 10953type booleanMergeHeapItem struct { 10954 itr *bufBooleanIterator 10955} 10956 10957// booleanSortedMergeIterator is an iterator that sorts and merges multiple iterators into one. 10958type booleanSortedMergeIterator struct { 10959 inputs []BooleanIterator 10960 heap *booleanSortedMergeHeap 10961 init bool 10962} 10963 10964// newBooleanSortedMergeIterator returns an instance of booleanSortedMergeIterator. 10965func newBooleanSortedMergeIterator(inputs []BooleanIterator, opt IteratorOptions) Iterator { 10966 itr := &booleanSortedMergeIterator{ 10967 inputs: inputs, 10968 heap: &booleanSortedMergeHeap{ 10969 items: make([]*booleanSortedMergeHeapItem, 0, len(inputs)), 10970 opt: opt, 10971 }, 10972 } 10973 10974 // Initialize heap items. 10975 for _, input := range inputs { 10976 // Append to the heap. 10977 itr.heap.items = append(itr.heap.items, &booleanSortedMergeHeapItem{itr: input}) 10978 } 10979 10980 return itr 10981} 10982 10983// Stats returns an aggregation of stats from the underlying iterators. 10984func (itr *booleanSortedMergeIterator) Stats() IteratorStats { 10985 var stats IteratorStats 10986 for _, input := range itr.inputs { 10987 stats.Add(input.Stats()) 10988 } 10989 return stats 10990} 10991 10992// Close closes the underlying iterators. 10993func (itr *booleanSortedMergeIterator) Close() error { 10994 for _, input := range itr.inputs { 10995 input.Close() 10996 } 10997 return nil 10998} 10999 11000// Next returns the next points from the iterator. 11001func (itr *booleanSortedMergeIterator) Next() (*BooleanPoint, error) { return itr.pop() } 11002 11003// pop returns the next point from the heap. 11004// Reads the next point from item's cursor and puts it back on the heap. 11005func (itr *booleanSortedMergeIterator) pop() (*BooleanPoint, error) { 11006 // Initialize the heap. See the MergeIterator to see why this has to be done lazily. 11007 if !itr.init { 11008 items := itr.heap.items 11009 itr.heap.items = make([]*booleanSortedMergeHeapItem, 0, len(items)) 11010 for _, item := range items { 11011 var err error 11012 if item.point, err = item.itr.Next(); err != nil { 11013 return nil, err 11014 } else if item.point == nil { 11015 continue 11016 } 11017 itr.heap.items = append(itr.heap.items, item) 11018 } 11019 heap.Init(itr.heap) 11020 itr.init = true 11021 } 11022 11023 if len(itr.heap.items) == 0 { 11024 return nil, nil 11025 } 11026 11027 // Read the next item from the heap. 11028 item := heap.Pop(itr.heap).(*booleanSortedMergeHeapItem) 11029 if item.err != nil { 11030 return nil, item.err 11031 } else if item.point == nil { 11032 return nil, nil 11033 } 11034 11035 // Copy the point for return. 11036 p := item.point.Clone() 11037 11038 // Read the next item from the cursor. Push back to heap if one exists. 11039 if item.point, item.err = item.itr.Next(); item.point != nil { 11040 heap.Push(itr.heap, item) 11041 } 11042 11043 return p, nil 11044} 11045 11046// booleanSortedMergeHeap represents a heap of booleanSortedMergeHeapItems. 11047// Items are sorted with the following priority: 11048// - By their measurement name; 11049// - By their tag keys/values; 11050// - By time; or 11051// - By their Aux field values. 11052// 11053type booleanSortedMergeHeap struct { 11054 opt IteratorOptions 11055 items []*booleanSortedMergeHeapItem 11056} 11057 11058func (h *booleanSortedMergeHeap) Len() int { return len(h.items) } 11059func (h *booleanSortedMergeHeap) Swap(i, j int) { h.items[i], h.items[j] = h.items[j], h.items[i] } 11060func (h *booleanSortedMergeHeap) Less(i, j int) bool { 11061 x, y := h.items[i].point, h.items[j].point 11062 11063 if h.opt.Ascending { 11064 if x.Name != y.Name { 11065 return x.Name < y.Name 11066 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); !xTags.Equals(&yTags) { 11067 return xTags.ID() < yTags.ID() 11068 } 11069 11070 if x.Time != y.Time { 11071 return x.Time < y.Time 11072 } 11073 11074 if len(x.Aux) > 0 && len(x.Aux) == len(y.Aux) { 11075 for i := 0; i < len(x.Aux); i++ { 11076 v1, ok1 := x.Aux[i].(string) 11077 v2, ok2 := y.Aux[i].(string) 11078 if !ok1 || !ok2 { 11079 // Unsupported types used in Aux fields. Maybe they 11080 // need to be added here? 11081 return false 11082 } else if v1 == v2 { 11083 continue 11084 } 11085 return v1 < v2 11086 } 11087 } 11088 return false // Times and/or Aux fields are equal. 11089 } 11090 11091 if x.Name != y.Name { 11092 return x.Name > y.Name 11093 } else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); !xTags.Equals(&yTags) { 11094 return xTags.ID() > yTags.ID() 11095 } 11096 11097 if x.Time != y.Time { 11098 return x.Time > y.Time 11099 } 11100 11101 if len(x.Aux) > 0 && len(x.Aux) == len(y.Aux) { 11102 for i := 0; i < len(x.Aux); i++ { 11103 v1, ok1 := x.Aux[i].(string) 11104 v2, ok2 := y.Aux[i].(string) 11105 if !ok1 || !ok2 { 11106 // Unsupported types used in Aux fields. Maybe they 11107 // need to be added here? 11108 return false 11109 } else if v1 == v2 { 11110 continue 11111 } 11112 return v1 > v2 11113 } 11114 } 11115 return false // Times and/or Aux fields are equal. 11116} 11117 11118func (h *booleanSortedMergeHeap) Push(x interface{}) { 11119 h.items = append(h.items, x.(*booleanSortedMergeHeapItem)) 11120} 11121 11122func (h *booleanSortedMergeHeap) Pop() interface{} { 11123 old := h.items 11124 n := len(old) 11125 item := old[n-1] 11126 h.items = old[0 : n-1] 11127 return item 11128} 11129 11130type booleanSortedMergeHeapItem struct { 11131 point *BooleanPoint 11132 err error 11133 itr BooleanIterator 11134} 11135 11136// booleanIteratorScanner scans the results of a BooleanIterator into a map. 11137type booleanIteratorScanner struct { 11138 input *bufBooleanIterator 11139 err error 11140 keys []influxql.VarRef 11141 defaultValue interface{} 11142} 11143 11144// newBooleanIteratorScanner creates a new IteratorScanner. 11145func newBooleanIteratorScanner(input BooleanIterator, keys []influxql.VarRef, defaultValue interface{}) *booleanIteratorScanner { 11146 return &booleanIteratorScanner{ 11147 input: newBufBooleanIterator(input), 11148 keys: keys, 11149 defaultValue: defaultValue, 11150 } 11151} 11152 11153func (s *booleanIteratorScanner) Peek() (int64, string, Tags) { 11154 if s.err != nil { 11155 return ZeroTime, "", Tags{} 11156 } 11157 11158 p, err := s.input.peek() 11159 if err != nil { 11160 s.err = err 11161 return ZeroTime, "", Tags{} 11162 } else if p == nil { 11163 return ZeroTime, "", Tags{} 11164 } 11165 return p.Time, p.Name, p.Tags 11166} 11167 11168func (s *booleanIteratorScanner) ScanAt(ts int64, name string, tags Tags, m map[string]interface{}) { 11169 if s.err != nil { 11170 return 11171 } 11172 11173 p, err := s.input.Next() 11174 if err != nil { 11175 s.err = err 11176 return 11177 } else if p == nil { 11178 s.useDefaults(m) 11179 return 11180 } else if p.Time != ts || p.Name != name || !p.Tags.Equals(&tags) { 11181 s.useDefaults(m) 11182 s.input.unread(p) 11183 return 11184 } 11185 11186 if k := s.keys[0]; k.Val != "" { 11187 if p.Nil { 11188 if s.defaultValue != SkipDefault { 11189 m[k.Val] = castToType(s.defaultValue, k.Type) 11190 } 11191 } else { 11192 m[k.Val] = p.Value 11193 } 11194 } 11195 for i, v := range p.Aux { 11196 k := s.keys[i+1] 11197 switch v.(type) { 11198 case float64, int64, uint64, string, bool: 11199 m[k.Val] = v 11200 default: 11201 // Insert the fill value if one was specified. 11202 if s.defaultValue != SkipDefault { 11203 m[k.Val] = castToType(s.defaultValue, k.Type) 11204 } 11205 } 11206 } 11207} 11208 11209func (s *booleanIteratorScanner) useDefaults(m map[string]interface{}) { 11210 if s.defaultValue == SkipDefault { 11211 return 11212 } 11213 for _, k := range s.keys { 11214 if k.Val == "" { 11215 continue 11216 } 11217 m[k.Val] = castToType(s.defaultValue, k.Type) 11218 } 11219} 11220 11221func (s *booleanIteratorScanner) Stats() IteratorStats { return s.input.Stats() } 11222func (s *booleanIteratorScanner) Err() error { return s.err } 11223func (s *booleanIteratorScanner) Close() error { return s.input.Close() } 11224 11225// booleanParallelIterator represents an iterator that pulls data in a separate goroutine. 11226type booleanParallelIterator struct { 11227 input BooleanIterator 11228 ch chan booleanPointError 11229 11230 once sync.Once 11231 closing chan struct{} 11232 wg sync.WaitGroup 11233} 11234 11235// newBooleanParallelIterator returns a new instance of booleanParallelIterator. 11236func newBooleanParallelIterator(input BooleanIterator) *booleanParallelIterator { 11237 itr := &booleanParallelIterator{ 11238 input: input, 11239 ch: make(chan booleanPointError, 256), 11240 closing: make(chan struct{}), 11241 } 11242 itr.wg.Add(1) 11243 go itr.monitor() 11244 return itr 11245} 11246 11247// Stats returns stats from the underlying iterator. 11248func (itr *booleanParallelIterator) Stats() IteratorStats { return itr.input.Stats() } 11249 11250// Close closes the underlying iterators. 11251func (itr *booleanParallelIterator) Close() error { 11252 itr.once.Do(func() { close(itr.closing) }) 11253 itr.wg.Wait() 11254 return itr.input.Close() 11255} 11256 11257// Next returns the next point from the iterator. 11258func (itr *booleanParallelIterator) Next() (*BooleanPoint, error) { 11259 v, ok := <-itr.ch 11260 if !ok { 11261 return nil, io.EOF 11262 } 11263 return v.point, v.err 11264} 11265 11266// monitor runs in a separate goroutine and actively pulls the next point. 11267func (itr *booleanParallelIterator) monitor() { 11268 defer close(itr.ch) 11269 defer itr.wg.Done() 11270 11271 for { 11272 // Read next point. 11273 p, err := itr.input.Next() 11274 if p != nil { 11275 p = p.Clone() 11276 } 11277 11278 select { 11279 case <-itr.closing: 11280 return 11281 case itr.ch <- booleanPointError{point: p, err: err}: 11282 } 11283 } 11284} 11285 11286type booleanPointError struct { 11287 point *BooleanPoint 11288 err error 11289} 11290 11291// booleanLimitIterator represents an iterator that limits points per group. 11292type booleanLimitIterator struct { 11293 input BooleanIterator 11294 opt IteratorOptions 11295 n int 11296 11297 prev struct { 11298 name string 11299 tags Tags 11300 } 11301} 11302 11303// newBooleanLimitIterator returns a new instance of booleanLimitIterator. 11304func newBooleanLimitIterator(input BooleanIterator, opt IteratorOptions) *booleanLimitIterator { 11305 return &booleanLimitIterator{ 11306 input: input, 11307 opt: opt, 11308 } 11309} 11310 11311// Stats returns stats from the underlying iterator. 11312func (itr *booleanLimitIterator) Stats() IteratorStats { return itr.input.Stats() } 11313 11314// Close closes the underlying iterators. 11315func (itr *booleanLimitIterator) Close() error { return itr.input.Close() } 11316 11317// Next returns the next point from the iterator. 11318func (itr *booleanLimitIterator) Next() (*BooleanPoint, error) { 11319 for { 11320 p, err := itr.input.Next() 11321 if p == nil || err != nil { 11322 return nil, err 11323 } 11324 11325 // Reset window and counter if a new window is encountered. 11326 if p.Name != itr.prev.name || !p.Tags.Equals(&itr.prev.tags) { 11327 itr.prev.name = p.Name 11328 itr.prev.tags = p.Tags 11329 itr.n = 0 11330 } 11331 11332 // Increment counter. 11333 itr.n++ 11334 11335 // Read next point if not beyond the offset. 11336 if itr.n <= itr.opt.Offset { 11337 continue 11338 } 11339 11340 // Read next point if we're beyond the limit. 11341 if itr.opt.Limit > 0 && (itr.n-itr.opt.Offset) > itr.opt.Limit { 11342 continue 11343 } 11344 11345 return p, nil 11346 } 11347} 11348 11349type booleanFillIterator struct { 11350 input *bufBooleanIterator 11351 prev BooleanPoint 11352 startTime int64 11353 endTime int64 11354 auxFields []interface{} 11355 init bool 11356 opt IteratorOptions 11357 11358 window struct { 11359 name string 11360 tags Tags 11361 time int64 11362 offset int64 11363 } 11364} 11365 11366func newBooleanFillIterator(input BooleanIterator, expr influxql.Expr, opt IteratorOptions) *booleanFillIterator { 11367 if opt.Fill == influxql.NullFill { 11368 if expr, ok := expr.(*influxql.Call); ok && expr.Name == "count" { 11369 opt.Fill = influxql.NumberFill 11370 opt.FillValue = false 11371 } 11372 } 11373 11374 var startTime, endTime int64 11375 if opt.Ascending { 11376 startTime, _ = opt.Window(opt.StartTime) 11377 endTime, _ = opt.Window(opt.EndTime) 11378 } else { 11379 startTime, _ = opt.Window(opt.EndTime) 11380 endTime, _ = opt.Window(opt.StartTime) 11381 } 11382 11383 var auxFields []interface{} 11384 if len(opt.Aux) > 0 { 11385 auxFields = make([]interface{}, len(opt.Aux)) 11386 } 11387 11388 return &booleanFillIterator{ 11389 input: newBufBooleanIterator(input), 11390 prev: BooleanPoint{Nil: true}, 11391 startTime: startTime, 11392 endTime: endTime, 11393 auxFields: auxFields, 11394 opt: opt, 11395 } 11396} 11397 11398func (itr *booleanFillIterator) Stats() IteratorStats { return itr.input.Stats() } 11399func (itr *booleanFillIterator) Close() error { return itr.input.Close() } 11400 11401func (itr *booleanFillIterator) Next() (*BooleanPoint, error) { 11402 if !itr.init { 11403 p, err := itr.input.peek() 11404 if p == nil || err != nil { 11405 return nil, err 11406 } 11407 itr.window.name, itr.window.tags = p.Name, p.Tags 11408 itr.window.time = itr.startTime 11409 if itr.startTime == influxql.MinTime { 11410 itr.window.time, _ = itr.opt.Window(p.Time) 11411 } 11412 if itr.opt.Location != nil { 11413 _, itr.window.offset = itr.opt.Zone(itr.window.time) 11414 } 11415 itr.init = true 11416 } 11417 11418 p, err := itr.input.Next() 11419 if err != nil { 11420 return nil, err 11421 } 11422 11423 // Check if the next point is outside of our window or is nil. 11424 if p == nil || p.Name != itr.window.name || p.Tags.ID() != itr.window.tags.ID() { 11425 // If we are inside of an interval, unread the point and continue below to 11426 // constructing a new point. 11427 if itr.opt.Ascending && itr.window.time <= itr.endTime { 11428 itr.input.unread(p) 11429 p = nil 11430 goto CONSTRUCT 11431 } else if !itr.opt.Ascending && itr.window.time >= itr.endTime && itr.endTime != influxql.MinTime { 11432 itr.input.unread(p) 11433 p = nil 11434 goto CONSTRUCT 11435 } 11436 11437 // We are *not* in a current interval. If there is no next point, 11438 // we are at the end of all intervals. 11439 if p == nil { 11440 return nil, nil 11441 } 11442 11443 // Set the new interval. 11444 itr.window.name, itr.window.tags = p.Name, p.Tags 11445 itr.window.time = itr.startTime 11446 if itr.window.time == influxql.MinTime { 11447 itr.window.time, _ = itr.opt.Window(p.Time) 11448 } 11449 if itr.opt.Location != nil { 11450 _, itr.window.offset = itr.opt.Zone(itr.window.time) 11451 } 11452 itr.prev = BooleanPoint{Nil: true} 11453 } 11454 11455 // Check if the point is our next expected point. 11456CONSTRUCT: 11457 if p == nil || (itr.opt.Ascending && p.Time > itr.window.time) || (!itr.opt.Ascending && p.Time < itr.window.time) { 11458 if p != nil { 11459 itr.input.unread(p) 11460 } 11461 11462 p = &BooleanPoint{ 11463 Name: itr.window.name, 11464 Tags: itr.window.tags, 11465 Time: itr.window.time, 11466 Aux: itr.auxFields, 11467 } 11468 11469 switch itr.opt.Fill { 11470 case influxql.LinearFill: 11471 fallthrough 11472 case influxql.NullFill: 11473 p.Nil = true 11474 case influxql.NumberFill: 11475 p.Value, _ = castToBoolean(itr.opt.FillValue) 11476 case influxql.PreviousFill: 11477 if !itr.prev.Nil { 11478 p.Value = itr.prev.Value 11479 p.Nil = itr.prev.Nil 11480 } else { 11481 p.Nil = true 11482 } 11483 } 11484 } else { 11485 itr.prev = *p 11486 } 11487 11488 // Advance the expected time. Do not advance to a new window here 11489 // as there may be lingering points with the same timestamp in the previous 11490 // window. 11491 if itr.opt.Ascending { 11492 itr.window.time += int64(itr.opt.Interval.Duration) 11493 } else { 11494 itr.window.time -= int64(itr.opt.Interval.Duration) 11495 } 11496 11497 // Check to see if we have passed over an offset change and adjust the time 11498 // to account for this new offset. 11499 if itr.opt.Location != nil { 11500 if _, offset := itr.opt.Zone(itr.window.time - 1); offset != itr.window.offset { 11501 diff := itr.window.offset - offset 11502 if abs(diff) < int64(itr.opt.Interval.Duration) { 11503 itr.window.time += diff 11504 } 11505 itr.window.offset = offset 11506 } 11507 } 11508 return p, nil 11509} 11510 11511// booleanIntervalIterator represents a boolean implementation of IntervalIterator. 11512type booleanIntervalIterator struct { 11513 input BooleanIterator 11514 opt IteratorOptions 11515} 11516 11517func newBooleanIntervalIterator(input BooleanIterator, opt IteratorOptions) *booleanIntervalIterator { 11518 return &booleanIntervalIterator{input: input, opt: opt} 11519} 11520 11521func (itr *booleanIntervalIterator) Stats() IteratorStats { return itr.input.Stats() } 11522func (itr *booleanIntervalIterator) Close() error { return itr.input.Close() } 11523 11524func (itr *booleanIntervalIterator) Next() (*BooleanPoint, error) { 11525 p, err := itr.input.Next() 11526 if p == nil || err != nil { 11527 return nil, err 11528 } 11529 p.Time, _ = itr.opt.Window(p.Time) 11530 // If we see the minimum allowable time, set the time to zero so we don't 11531 // break the default returned time for aggregate queries without times. 11532 if p.Time == influxql.MinTime { 11533 p.Time = 0 11534 } 11535 return p, nil 11536} 11537 11538// booleanInterruptIterator represents a boolean implementation of InterruptIterator. 11539type booleanInterruptIterator struct { 11540 input BooleanIterator 11541 closing <-chan struct{} 11542 count int 11543} 11544 11545func newBooleanInterruptIterator(input BooleanIterator, closing <-chan struct{}) *booleanInterruptIterator { 11546 return &booleanInterruptIterator{input: input, closing: closing} 11547} 11548 11549func (itr *booleanInterruptIterator) Stats() IteratorStats { return itr.input.Stats() } 11550func (itr *booleanInterruptIterator) Close() error { return itr.input.Close() } 11551 11552func (itr *booleanInterruptIterator) Next() (*BooleanPoint, error) { 11553 // Only check if the channel is closed every N points. This 11554 // intentionally checks on both 0 and N so that if the iterator 11555 // has been interrupted before the first point is emitted it will 11556 // not emit any points. 11557 if itr.count&0xFF == 0xFF { 11558 select { 11559 case <-itr.closing: 11560 return nil, itr.Close() 11561 default: 11562 // Reset iterator count to zero and fall through to emit the next point. 11563 itr.count = 0 11564 } 11565 } 11566 11567 // Increment the counter for every point read. 11568 itr.count++ 11569 return itr.input.Next() 11570} 11571 11572// booleanCloseInterruptIterator represents a boolean implementation of CloseInterruptIterator. 11573type booleanCloseInterruptIterator struct { 11574 input BooleanIterator 11575 closing <-chan struct{} 11576 done chan struct{} 11577 once sync.Once 11578} 11579 11580func newBooleanCloseInterruptIterator(input BooleanIterator, closing <-chan struct{}) *booleanCloseInterruptIterator { 11581 itr := &booleanCloseInterruptIterator{ 11582 input: input, 11583 closing: closing, 11584 done: make(chan struct{}), 11585 } 11586 go itr.monitor() 11587 return itr 11588} 11589 11590func (itr *booleanCloseInterruptIterator) monitor() { 11591 select { 11592 case <-itr.closing: 11593 itr.Close() 11594 case <-itr.done: 11595 } 11596} 11597 11598func (itr *booleanCloseInterruptIterator) Stats() IteratorStats { 11599 return itr.input.Stats() 11600} 11601 11602func (itr *booleanCloseInterruptIterator) Close() error { 11603 itr.once.Do(func() { 11604 close(itr.done) 11605 itr.input.Close() 11606 }) 11607 return nil 11608} 11609 11610func (itr *booleanCloseInterruptIterator) Next() (*BooleanPoint, error) { 11611 p, err := itr.input.Next() 11612 if err != nil { 11613 // Check if the iterator was closed. 11614 select { 11615 case <-itr.done: 11616 return nil, nil 11617 default: 11618 return nil, err 11619 } 11620 } 11621 return p, nil 11622} 11623 11624// booleanReduceFloatIterator executes a reducer for every interval and buffers the result. 11625type booleanReduceFloatIterator struct { 11626 input *bufBooleanIterator 11627 create func() (BooleanPointAggregator, FloatPointEmitter) 11628 dims []string 11629 opt IteratorOptions 11630 points []FloatPoint 11631 keepTags bool 11632} 11633 11634func newBooleanReduceFloatIterator(input BooleanIterator, opt IteratorOptions, createFn func() (BooleanPointAggregator, FloatPointEmitter)) *booleanReduceFloatIterator { 11635 return &booleanReduceFloatIterator{ 11636 input: newBufBooleanIterator(input), 11637 create: createFn, 11638 dims: opt.GetDimensions(), 11639 opt: opt, 11640 } 11641} 11642 11643// Stats returns stats from the input iterator. 11644func (itr *booleanReduceFloatIterator) Stats() IteratorStats { return itr.input.Stats() } 11645 11646// Close closes the iterator and all child iterators. 11647func (itr *booleanReduceFloatIterator) Close() error { return itr.input.Close() } 11648 11649// Next returns the minimum value for the next available interval. 11650func (itr *booleanReduceFloatIterator) Next() (*FloatPoint, error) { 11651 // Calculate next window if we have no more points. 11652 if len(itr.points) == 0 { 11653 var err error 11654 itr.points, err = itr.reduce() 11655 if len(itr.points) == 0 { 11656 return nil, err 11657 } 11658 } 11659 11660 // Pop next point off the stack. 11661 p := &itr.points[len(itr.points)-1] 11662 itr.points = itr.points[:len(itr.points)-1] 11663 return p, nil 11664} 11665 11666// booleanReduceFloatPoint stores the reduced data for a name/tag combination. 11667type booleanReduceFloatPoint struct { 11668 Name string 11669 Tags Tags 11670 Aggregator BooleanPointAggregator 11671 Emitter FloatPointEmitter 11672} 11673 11674// reduce executes fn once for every point in the next window. 11675// The previous value for the dimension is passed to fn. 11676func (itr *booleanReduceFloatIterator) reduce() ([]FloatPoint, error) { 11677 // Calculate next window. 11678 var ( 11679 startTime, endTime int64 11680 window struct { 11681 name string 11682 tags string 11683 } 11684 ) 11685 for { 11686 p, err := itr.input.Next() 11687 if err != nil || p == nil { 11688 return nil, err 11689 } else if p.Nil { 11690 continue 11691 } 11692 11693 // Unread the point so it can be processed. 11694 itr.input.unread(p) 11695 startTime, endTime = itr.opt.Window(p.Time) 11696 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 11697 break 11698 } 11699 11700 // Create points by tags. 11701 m := make(map[string]*booleanReduceFloatPoint) 11702 for { 11703 // Read next point. 11704 curr, err := itr.input.NextInWindow(startTime, endTime) 11705 if err != nil { 11706 return nil, err 11707 } else if curr == nil { 11708 break 11709 } else if curr.Nil { 11710 continue 11711 } else if curr.Name != window.name { 11712 itr.input.unread(curr) 11713 break 11714 } 11715 11716 // Ensure this point is within the same final window. 11717 if curr.Name != window.name { 11718 itr.input.unread(curr) 11719 break 11720 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 11721 itr.input.unread(curr) 11722 break 11723 } 11724 11725 // Retrieve the tags on this point for this level of the query. 11726 // This may be different than the bucket dimensions. 11727 tags := curr.Tags.Subset(itr.dims) 11728 id := tags.ID() 11729 11730 // Retrieve the aggregator for this name/tag combination or create one. 11731 rp := m[id] 11732 if rp == nil { 11733 aggregator, emitter := itr.create() 11734 rp = &booleanReduceFloatPoint{ 11735 Name: curr.Name, 11736 Tags: tags, 11737 Aggregator: aggregator, 11738 Emitter: emitter, 11739 } 11740 m[id] = rp 11741 } 11742 rp.Aggregator.AggregateBoolean(curr) 11743 } 11744 11745 keys := make([]string, 0, len(m)) 11746 for k := range m { 11747 keys = append(keys, k) 11748 } 11749 11750 // Reverse sort points by name & tag. 11751 // This ensures a consistent order of output. 11752 if len(keys) > 0 { 11753 var sorted sort.Interface = sort.StringSlice(keys) 11754 if itr.opt.Ascending { 11755 sorted = sort.Reverse(sorted) 11756 } 11757 sort.Sort(sorted) 11758 } 11759 11760 // Assume the points are already sorted until proven otherwise. 11761 sortedByTime := true 11762 // Emit the points for each name & tag combination. 11763 a := make([]FloatPoint, 0, len(m)) 11764 for _, k := range keys { 11765 rp := m[k] 11766 points := rp.Emitter.Emit() 11767 for i := len(points) - 1; i >= 0; i-- { 11768 points[i].Name = rp.Name 11769 if !itr.keepTags { 11770 points[i].Tags = rp.Tags 11771 } 11772 // Set the points time to the interval time if the reducer didn't provide one. 11773 if points[i].Time == ZeroTime { 11774 points[i].Time = startTime 11775 } else { 11776 sortedByTime = false 11777 } 11778 a = append(a, points[i]) 11779 } 11780 } 11781 // Points may be out of order. Perform a stable sort by time if requested. 11782 if !sortedByTime && itr.opt.Ordered { 11783 var sorted sort.Interface = floatPointsByTime(a) 11784 if itr.opt.Ascending { 11785 sorted = sort.Reverse(sorted) 11786 } 11787 sort.Stable(sorted) 11788 } 11789 return a, nil 11790} 11791 11792// booleanStreamFloatIterator streams inputs into the iterator and emits points gradually. 11793type booleanStreamFloatIterator struct { 11794 input *bufBooleanIterator 11795 create func() (BooleanPointAggregator, FloatPointEmitter) 11796 dims []string 11797 opt IteratorOptions 11798 m map[string]*booleanReduceFloatPoint 11799 points []FloatPoint 11800} 11801 11802// newBooleanStreamFloatIterator returns a new instance of booleanStreamFloatIterator. 11803func newBooleanStreamFloatIterator(input BooleanIterator, createFn func() (BooleanPointAggregator, FloatPointEmitter), opt IteratorOptions) *booleanStreamFloatIterator { 11804 return &booleanStreamFloatIterator{ 11805 input: newBufBooleanIterator(input), 11806 create: createFn, 11807 dims: opt.GetDimensions(), 11808 opt: opt, 11809 m: make(map[string]*booleanReduceFloatPoint), 11810 } 11811} 11812 11813// Stats returns stats from the input iterator. 11814func (itr *booleanStreamFloatIterator) Stats() IteratorStats { return itr.input.Stats() } 11815 11816// Close closes the iterator and all child iterators. 11817func (itr *booleanStreamFloatIterator) Close() error { return itr.input.Close() } 11818 11819// Next returns the next value for the stream iterator. 11820func (itr *booleanStreamFloatIterator) Next() (*FloatPoint, error) { 11821 // Calculate next window if we have no more points. 11822 if len(itr.points) == 0 { 11823 var err error 11824 itr.points, err = itr.reduce() 11825 if len(itr.points) == 0 { 11826 return nil, err 11827 } 11828 } 11829 11830 // Pop next point off the stack. 11831 p := &itr.points[len(itr.points)-1] 11832 itr.points = itr.points[:len(itr.points)-1] 11833 return p, nil 11834} 11835 11836// reduce creates and manages aggregators for every point from the input. 11837// After aggregating a point, it always tries to emit a value using the emitter. 11838func (itr *booleanStreamFloatIterator) reduce() ([]FloatPoint, error) { 11839 // We have already read all of the input points. 11840 if itr.m == nil { 11841 return nil, nil 11842 } 11843 11844 for { 11845 // Read next point. 11846 curr, err := itr.input.Next() 11847 if err != nil { 11848 return nil, err 11849 } else if curr == nil { 11850 // Close all of the aggregators to flush any remaining points to emit. 11851 var points []FloatPoint 11852 for _, rp := range itr.m { 11853 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 11854 if err := aggregator.Close(); err != nil { 11855 return nil, err 11856 } 11857 11858 pts := rp.Emitter.Emit() 11859 if len(pts) == 0 { 11860 continue 11861 } 11862 11863 for i := range pts { 11864 pts[i].Name = rp.Name 11865 pts[i].Tags = rp.Tags 11866 } 11867 points = append(points, pts...) 11868 } 11869 } 11870 11871 // Eliminate the aggregators and emitters. 11872 itr.m = nil 11873 return points, nil 11874 } else if curr.Nil { 11875 continue 11876 } 11877 tags := curr.Tags.Subset(itr.dims) 11878 11879 id := curr.Name 11880 if len(tags.m) > 0 { 11881 id += "\x00" + tags.ID() 11882 } 11883 11884 // Retrieve the aggregator for this name/tag combination or create one. 11885 rp := itr.m[id] 11886 if rp == nil { 11887 aggregator, emitter := itr.create() 11888 rp = &booleanReduceFloatPoint{ 11889 Name: curr.Name, 11890 Tags: tags, 11891 Aggregator: aggregator, 11892 Emitter: emitter, 11893 } 11894 itr.m[id] = rp 11895 } 11896 rp.Aggregator.AggregateBoolean(curr) 11897 11898 // Attempt to emit points from the aggregator. 11899 points := rp.Emitter.Emit() 11900 if len(points) == 0 { 11901 continue 11902 } 11903 11904 for i := range points { 11905 points[i].Name = rp.Name 11906 points[i].Tags = rp.Tags 11907 } 11908 return points, nil 11909 } 11910} 11911 11912// booleanReduceIntegerIterator executes a reducer for every interval and buffers the result. 11913type booleanReduceIntegerIterator struct { 11914 input *bufBooleanIterator 11915 create func() (BooleanPointAggregator, IntegerPointEmitter) 11916 dims []string 11917 opt IteratorOptions 11918 points []IntegerPoint 11919 keepTags bool 11920} 11921 11922func newBooleanReduceIntegerIterator(input BooleanIterator, opt IteratorOptions, createFn func() (BooleanPointAggregator, IntegerPointEmitter)) *booleanReduceIntegerIterator { 11923 return &booleanReduceIntegerIterator{ 11924 input: newBufBooleanIterator(input), 11925 create: createFn, 11926 dims: opt.GetDimensions(), 11927 opt: opt, 11928 } 11929} 11930 11931// Stats returns stats from the input iterator. 11932func (itr *booleanReduceIntegerIterator) Stats() IteratorStats { return itr.input.Stats() } 11933 11934// Close closes the iterator and all child iterators. 11935func (itr *booleanReduceIntegerIterator) Close() error { return itr.input.Close() } 11936 11937// Next returns the minimum value for the next available interval. 11938func (itr *booleanReduceIntegerIterator) Next() (*IntegerPoint, error) { 11939 // Calculate next window if we have no more points. 11940 if len(itr.points) == 0 { 11941 var err error 11942 itr.points, err = itr.reduce() 11943 if len(itr.points) == 0 { 11944 return nil, err 11945 } 11946 } 11947 11948 // Pop next point off the stack. 11949 p := &itr.points[len(itr.points)-1] 11950 itr.points = itr.points[:len(itr.points)-1] 11951 return p, nil 11952} 11953 11954// booleanReduceIntegerPoint stores the reduced data for a name/tag combination. 11955type booleanReduceIntegerPoint struct { 11956 Name string 11957 Tags Tags 11958 Aggregator BooleanPointAggregator 11959 Emitter IntegerPointEmitter 11960} 11961 11962// reduce executes fn once for every point in the next window. 11963// The previous value for the dimension is passed to fn. 11964func (itr *booleanReduceIntegerIterator) reduce() ([]IntegerPoint, error) { 11965 // Calculate next window. 11966 var ( 11967 startTime, endTime int64 11968 window struct { 11969 name string 11970 tags string 11971 } 11972 ) 11973 for { 11974 p, err := itr.input.Next() 11975 if err != nil || p == nil { 11976 return nil, err 11977 } else if p.Nil { 11978 continue 11979 } 11980 11981 // Unread the point so it can be processed. 11982 itr.input.unread(p) 11983 startTime, endTime = itr.opt.Window(p.Time) 11984 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 11985 break 11986 } 11987 11988 // Create points by tags. 11989 m := make(map[string]*booleanReduceIntegerPoint) 11990 for { 11991 // Read next point. 11992 curr, err := itr.input.NextInWindow(startTime, endTime) 11993 if err != nil { 11994 return nil, err 11995 } else if curr == nil { 11996 break 11997 } else if curr.Nil { 11998 continue 11999 } else if curr.Name != window.name { 12000 itr.input.unread(curr) 12001 break 12002 } 12003 12004 // Ensure this point is within the same final window. 12005 if curr.Name != window.name { 12006 itr.input.unread(curr) 12007 break 12008 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 12009 itr.input.unread(curr) 12010 break 12011 } 12012 12013 // Retrieve the tags on this point for this level of the query. 12014 // This may be different than the bucket dimensions. 12015 tags := curr.Tags.Subset(itr.dims) 12016 id := tags.ID() 12017 12018 // Retrieve the aggregator for this name/tag combination or create one. 12019 rp := m[id] 12020 if rp == nil { 12021 aggregator, emitter := itr.create() 12022 rp = &booleanReduceIntegerPoint{ 12023 Name: curr.Name, 12024 Tags: tags, 12025 Aggregator: aggregator, 12026 Emitter: emitter, 12027 } 12028 m[id] = rp 12029 } 12030 rp.Aggregator.AggregateBoolean(curr) 12031 } 12032 12033 keys := make([]string, 0, len(m)) 12034 for k := range m { 12035 keys = append(keys, k) 12036 } 12037 12038 // Reverse sort points by name & tag. 12039 // This ensures a consistent order of output. 12040 if len(keys) > 0 { 12041 var sorted sort.Interface = sort.StringSlice(keys) 12042 if itr.opt.Ascending { 12043 sorted = sort.Reverse(sorted) 12044 } 12045 sort.Sort(sorted) 12046 } 12047 12048 // Assume the points are already sorted until proven otherwise. 12049 sortedByTime := true 12050 // Emit the points for each name & tag combination. 12051 a := make([]IntegerPoint, 0, len(m)) 12052 for _, k := range keys { 12053 rp := m[k] 12054 points := rp.Emitter.Emit() 12055 for i := len(points) - 1; i >= 0; i-- { 12056 points[i].Name = rp.Name 12057 if !itr.keepTags { 12058 points[i].Tags = rp.Tags 12059 } 12060 // Set the points time to the interval time if the reducer didn't provide one. 12061 if points[i].Time == ZeroTime { 12062 points[i].Time = startTime 12063 } else { 12064 sortedByTime = false 12065 } 12066 a = append(a, points[i]) 12067 } 12068 } 12069 // Points may be out of order. Perform a stable sort by time if requested. 12070 if !sortedByTime && itr.opt.Ordered { 12071 var sorted sort.Interface = integerPointsByTime(a) 12072 if itr.opt.Ascending { 12073 sorted = sort.Reverse(sorted) 12074 } 12075 sort.Stable(sorted) 12076 } 12077 return a, nil 12078} 12079 12080// booleanStreamIntegerIterator streams inputs into the iterator and emits points gradually. 12081type booleanStreamIntegerIterator struct { 12082 input *bufBooleanIterator 12083 create func() (BooleanPointAggregator, IntegerPointEmitter) 12084 dims []string 12085 opt IteratorOptions 12086 m map[string]*booleanReduceIntegerPoint 12087 points []IntegerPoint 12088} 12089 12090// newBooleanStreamIntegerIterator returns a new instance of booleanStreamIntegerIterator. 12091func newBooleanStreamIntegerIterator(input BooleanIterator, createFn func() (BooleanPointAggregator, IntegerPointEmitter), opt IteratorOptions) *booleanStreamIntegerIterator { 12092 return &booleanStreamIntegerIterator{ 12093 input: newBufBooleanIterator(input), 12094 create: createFn, 12095 dims: opt.GetDimensions(), 12096 opt: opt, 12097 m: make(map[string]*booleanReduceIntegerPoint), 12098 } 12099} 12100 12101// Stats returns stats from the input iterator. 12102func (itr *booleanStreamIntegerIterator) Stats() IteratorStats { return itr.input.Stats() } 12103 12104// Close closes the iterator and all child iterators. 12105func (itr *booleanStreamIntegerIterator) Close() error { return itr.input.Close() } 12106 12107// Next returns the next value for the stream iterator. 12108func (itr *booleanStreamIntegerIterator) Next() (*IntegerPoint, error) { 12109 // Calculate next window if we have no more points. 12110 if len(itr.points) == 0 { 12111 var err error 12112 itr.points, err = itr.reduce() 12113 if len(itr.points) == 0 { 12114 return nil, err 12115 } 12116 } 12117 12118 // Pop next point off the stack. 12119 p := &itr.points[len(itr.points)-1] 12120 itr.points = itr.points[:len(itr.points)-1] 12121 return p, nil 12122} 12123 12124// reduce creates and manages aggregators for every point from the input. 12125// After aggregating a point, it always tries to emit a value using the emitter. 12126func (itr *booleanStreamIntegerIterator) reduce() ([]IntegerPoint, error) { 12127 // We have already read all of the input points. 12128 if itr.m == nil { 12129 return nil, nil 12130 } 12131 12132 for { 12133 // Read next point. 12134 curr, err := itr.input.Next() 12135 if err != nil { 12136 return nil, err 12137 } else if curr == nil { 12138 // Close all of the aggregators to flush any remaining points to emit. 12139 var points []IntegerPoint 12140 for _, rp := range itr.m { 12141 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 12142 if err := aggregator.Close(); err != nil { 12143 return nil, err 12144 } 12145 12146 pts := rp.Emitter.Emit() 12147 if len(pts) == 0 { 12148 continue 12149 } 12150 12151 for i := range pts { 12152 pts[i].Name = rp.Name 12153 pts[i].Tags = rp.Tags 12154 } 12155 points = append(points, pts...) 12156 } 12157 } 12158 12159 // Eliminate the aggregators and emitters. 12160 itr.m = nil 12161 return points, nil 12162 } else if curr.Nil { 12163 continue 12164 } 12165 tags := curr.Tags.Subset(itr.dims) 12166 12167 id := curr.Name 12168 if len(tags.m) > 0 { 12169 id += "\x00" + tags.ID() 12170 } 12171 12172 // Retrieve the aggregator for this name/tag combination or create one. 12173 rp := itr.m[id] 12174 if rp == nil { 12175 aggregator, emitter := itr.create() 12176 rp = &booleanReduceIntegerPoint{ 12177 Name: curr.Name, 12178 Tags: tags, 12179 Aggregator: aggregator, 12180 Emitter: emitter, 12181 } 12182 itr.m[id] = rp 12183 } 12184 rp.Aggregator.AggregateBoolean(curr) 12185 12186 // Attempt to emit points from the aggregator. 12187 points := rp.Emitter.Emit() 12188 if len(points) == 0 { 12189 continue 12190 } 12191 12192 for i := range points { 12193 points[i].Name = rp.Name 12194 points[i].Tags = rp.Tags 12195 } 12196 return points, nil 12197 } 12198} 12199 12200// booleanReduceUnsignedIterator executes a reducer for every interval and buffers the result. 12201type booleanReduceUnsignedIterator struct { 12202 input *bufBooleanIterator 12203 create func() (BooleanPointAggregator, UnsignedPointEmitter) 12204 dims []string 12205 opt IteratorOptions 12206 points []UnsignedPoint 12207 keepTags bool 12208} 12209 12210func newBooleanReduceUnsignedIterator(input BooleanIterator, opt IteratorOptions, createFn func() (BooleanPointAggregator, UnsignedPointEmitter)) *booleanReduceUnsignedIterator { 12211 return &booleanReduceUnsignedIterator{ 12212 input: newBufBooleanIterator(input), 12213 create: createFn, 12214 dims: opt.GetDimensions(), 12215 opt: opt, 12216 } 12217} 12218 12219// Stats returns stats from the input iterator. 12220func (itr *booleanReduceUnsignedIterator) Stats() IteratorStats { return itr.input.Stats() } 12221 12222// Close closes the iterator and all child iterators. 12223func (itr *booleanReduceUnsignedIterator) Close() error { return itr.input.Close() } 12224 12225// Next returns the minimum value for the next available interval. 12226func (itr *booleanReduceUnsignedIterator) Next() (*UnsignedPoint, error) { 12227 // Calculate next window if we have no more points. 12228 if len(itr.points) == 0 { 12229 var err error 12230 itr.points, err = itr.reduce() 12231 if len(itr.points) == 0 { 12232 return nil, err 12233 } 12234 } 12235 12236 // Pop next point off the stack. 12237 p := &itr.points[len(itr.points)-1] 12238 itr.points = itr.points[:len(itr.points)-1] 12239 return p, nil 12240} 12241 12242// booleanReduceUnsignedPoint stores the reduced data for a name/tag combination. 12243type booleanReduceUnsignedPoint struct { 12244 Name string 12245 Tags Tags 12246 Aggregator BooleanPointAggregator 12247 Emitter UnsignedPointEmitter 12248} 12249 12250// reduce executes fn once for every point in the next window. 12251// The previous value for the dimension is passed to fn. 12252func (itr *booleanReduceUnsignedIterator) reduce() ([]UnsignedPoint, error) { 12253 // Calculate next window. 12254 var ( 12255 startTime, endTime int64 12256 window struct { 12257 name string 12258 tags string 12259 } 12260 ) 12261 for { 12262 p, err := itr.input.Next() 12263 if err != nil || p == nil { 12264 return nil, err 12265 } else if p.Nil { 12266 continue 12267 } 12268 12269 // Unread the point so it can be processed. 12270 itr.input.unread(p) 12271 startTime, endTime = itr.opt.Window(p.Time) 12272 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 12273 break 12274 } 12275 12276 // Create points by tags. 12277 m := make(map[string]*booleanReduceUnsignedPoint) 12278 for { 12279 // Read next point. 12280 curr, err := itr.input.NextInWindow(startTime, endTime) 12281 if err != nil { 12282 return nil, err 12283 } else if curr == nil { 12284 break 12285 } else if curr.Nil { 12286 continue 12287 } else if curr.Name != window.name { 12288 itr.input.unread(curr) 12289 break 12290 } 12291 12292 // Ensure this point is within the same final window. 12293 if curr.Name != window.name { 12294 itr.input.unread(curr) 12295 break 12296 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 12297 itr.input.unread(curr) 12298 break 12299 } 12300 12301 // Retrieve the tags on this point for this level of the query. 12302 // This may be different than the bucket dimensions. 12303 tags := curr.Tags.Subset(itr.dims) 12304 id := tags.ID() 12305 12306 // Retrieve the aggregator for this name/tag combination or create one. 12307 rp := m[id] 12308 if rp == nil { 12309 aggregator, emitter := itr.create() 12310 rp = &booleanReduceUnsignedPoint{ 12311 Name: curr.Name, 12312 Tags: tags, 12313 Aggregator: aggregator, 12314 Emitter: emitter, 12315 } 12316 m[id] = rp 12317 } 12318 rp.Aggregator.AggregateBoolean(curr) 12319 } 12320 12321 keys := make([]string, 0, len(m)) 12322 for k := range m { 12323 keys = append(keys, k) 12324 } 12325 12326 // Reverse sort points by name & tag. 12327 // This ensures a consistent order of output. 12328 if len(keys) > 0 { 12329 var sorted sort.Interface = sort.StringSlice(keys) 12330 if itr.opt.Ascending { 12331 sorted = sort.Reverse(sorted) 12332 } 12333 sort.Sort(sorted) 12334 } 12335 12336 // Assume the points are already sorted until proven otherwise. 12337 sortedByTime := true 12338 // Emit the points for each name & tag combination. 12339 a := make([]UnsignedPoint, 0, len(m)) 12340 for _, k := range keys { 12341 rp := m[k] 12342 points := rp.Emitter.Emit() 12343 for i := len(points) - 1; i >= 0; i-- { 12344 points[i].Name = rp.Name 12345 if !itr.keepTags { 12346 points[i].Tags = rp.Tags 12347 } 12348 // Set the points time to the interval time if the reducer didn't provide one. 12349 if points[i].Time == ZeroTime { 12350 points[i].Time = startTime 12351 } else { 12352 sortedByTime = false 12353 } 12354 a = append(a, points[i]) 12355 } 12356 } 12357 // Points may be out of order. Perform a stable sort by time if requested. 12358 if !sortedByTime && itr.opt.Ordered { 12359 var sorted sort.Interface = unsignedPointsByTime(a) 12360 if itr.opt.Ascending { 12361 sorted = sort.Reverse(sorted) 12362 } 12363 sort.Stable(sorted) 12364 } 12365 return a, nil 12366} 12367 12368// booleanStreamUnsignedIterator streams inputs into the iterator and emits points gradually. 12369type booleanStreamUnsignedIterator struct { 12370 input *bufBooleanIterator 12371 create func() (BooleanPointAggregator, UnsignedPointEmitter) 12372 dims []string 12373 opt IteratorOptions 12374 m map[string]*booleanReduceUnsignedPoint 12375 points []UnsignedPoint 12376} 12377 12378// newBooleanStreamUnsignedIterator returns a new instance of booleanStreamUnsignedIterator. 12379func newBooleanStreamUnsignedIterator(input BooleanIterator, createFn func() (BooleanPointAggregator, UnsignedPointEmitter), opt IteratorOptions) *booleanStreamUnsignedIterator { 12380 return &booleanStreamUnsignedIterator{ 12381 input: newBufBooleanIterator(input), 12382 create: createFn, 12383 dims: opt.GetDimensions(), 12384 opt: opt, 12385 m: make(map[string]*booleanReduceUnsignedPoint), 12386 } 12387} 12388 12389// Stats returns stats from the input iterator. 12390func (itr *booleanStreamUnsignedIterator) Stats() IteratorStats { return itr.input.Stats() } 12391 12392// Close closes the iterator and all child iterators. 12393func (itr *booleanStreamUnsignedIterator) Close() error { return itr.input.Close() } 12394 12395// Next returns the next value for the stream iterator. 12396func (itr *booleanStreamUnsignedIterator) Next() (*UnsignedPoint, error) { 12397 // Calculate next window if we have no more points. 12398 if len(itr.points) == 0 { 12399 var err error 12400 itr.points, err = itr.reduce() 12401 if len(itr.points) == 0 { 12402 return nil, err 12403 } 12404 } 12405 12406 // Pop next point off the stack. 12407 p := &itr.points[len(itr.points)-1] 12408 itr.points = itr.points[:len(itr.points)-1] 12409 return p, nil 12410} 12411 12412// reduce creates and manages aggregators for every point from the input. 12413// After aggregating a point, it always tries to emit a value using the emitter. 12414func (itr *booleanStreamUnsignedIterator) reduce() ([]UnsignedPoint, error) { 12415 // We have already read all of the input points. 12416 if itr.m == nil { 12417 return nil, nil 12418 } 12419 12420 for { 12421 // Read next point. 12422 curr, err := itr.input.Next() 12423 if err != nil { 12424 return nil, err 12425 } else if curr == nil { 12426 // Close all of the aggregators to flush any remaining points to emit. 12427 var points []UnsignedPoint 12428 for _, rp := range itr.m { 12429 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 12430 if err := aggregator.Close(); err != nil { 12431 return nil, err 12432 } 12433 12434 pts := rp.Emitter.Emit() 12435 if len(pts) == 0 { 12436 continue 12437 } 12438 12439 for i := range pts { 12440 pts[i].Name = rp.Name 12441 pts[i].Tags = rp.Tags 12442 } 12443 points = append(points, pts...) 12444 } 12445 } 12446 12447 // Eliminate the aggregators and emitters. 12448 itr.m = nil 12449 return points, nil 12450 } else if curr.Nil { 12451 continue 12452 } 12453 tags := curr.Tags.Subset(itr.dims) 12454 12455 id := curr.Name 12456 if len(tags.m) > 0 { 12457 id += "\x00" + tags.ID() 12458 } 12459 12460 // Retrieve the aggregator for this name/tag combination or create one. 12461 rp := itr.m[id] 12462 if rp == nil { 12463 aggregator, emitter := itr.create() 12464 rp = &booleanReduceUnsignedPoint{ 12465 Name: curr.Name, 12466 Tags: tags, 12467 Aggregator: aggregator, 12468 Emitter: emitter, 12469 } 12470 itr.m[id] = rp 12471 } 12472 rp.Aggregator.AggregateBoolean(curr) 12473 12474 // Attempt to emit points from the aggregator. 12475 points := rp.Emitter.Emit() 12476 if len(points) == 0 { 12477 continue 12478 } 12479 12480 for i := range points { 12481 points[i].Name = rp.Name 12482 points[i].Tags = rp.Tags 12483 } 12484 return points, nil 12485 } 12486} 12487 12488// booleanReduceStringIterator executes a reducer for every interval and buffers the result. 12489type booleanReduceStringIterator struct { 12490 input *bufBooleanIterator 12491 create func() (BooleanPointAggregator, StringPointEmitter) 12492 dims []string 12493 opt IteratorOptions 12494 points []StringPoint 12495 keepTags bool 12496} 12497 12498func newBooleanReduceStringIterator(input BooleanIterator, opt IteratorOptions, createFn func() (BooleanPointAggregator, StringPointEmitter)) *booleanReduceStringIterator { 12499 return &booleanReduceStringIterator{ 12500 input: newBufBooleanIterator(input), 12501 create: createFn, 12502 dims: opt.GetDimensions(), 12503 opt: opt, 12504 } 12505} 12506 12507// Stats returns stats from the input iterator. 12508func (itr *booleanReduceStringIterator) Stats() IteratorStats { return itr.input.Stats() } 12509 12510// Close closes the iterator and all child iterators. 12511func (itr *booleanReduceStringIterator) Close() error { return itr.input.Close() } 12512 12513// Next returns the minimum value for the next available interval. 12514func (itr *booleanReduceStringIterator) Next() (*StringPoint, error) { 12515 // Calculate next window if we have no more points. 12516 if len(itr.points) == 0 { 12517 var err error 12518 itr.points, err = itr.reduce() 12519 if len(itr.points) == 0 { 12520 return nil, err 12521 } 12522 } 12523 12524 // Pop next point off the stack. 12525 p := &itr.points[len(itr.points)-1] 12526 itr.points = itr.points[:len(itr.points)-1] 12527 return p, nil 12528} 12529 12530// booleanReduceStringPoint stores the reduced data for a name/tag combination. 12531type booleanReduceStringPoint struct { 12532 Name string 12533 Tags Tags 12534 Aggregator BooleanPointAggregator 12535 Emitter StringPointEmitter 12536} 12537 12538// reduce executes fn once for every point in the next window. 12539// The previous value for the dimension is passed to fn. 12540func (itr *booleanReduceStringIterator) reduce() ([]StringPoint, error) { 12541 // Calculate next window. 12542 var ( 12543 startTime, endTime int64 12544 window struct { 12545 name string 12546 tags string 12547 } 12548 ) 12549 for { 12550 p, err := itr.input.Next() 12551 if err != nil || p == nil { 12552 return nil, err 12553 } else if p.Nil { 12554 continue 12555 } 12556 12557 // Unread the point so it can be processed. 12558 itr.input.unread(p) 12559 startTime, endTime = itr.opt.Window(p.Time) 12560 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 12561 break 12562 } 12563 12564 // Create points by tags. 12565 m := make(map[string]*booleanReduceStringPoint) 12566 for { 12567 // Read next point. 12568 curr, err := itr.input.NextInWindow(startTime, endTime) 12569 if err != nil { 12570 return nil, err 12571 } else if curr == nil { 12572 break 12573 } else if curr.Nil { 12574 continue 12575 } else if curr.Name != window.name { 12576 itr.input.unread(curr) 12577 break 12578 } 12579 12580 // Ensure this point is within the same final window. 12581 if curr.Name != window.name { 12582 itr.input.unread(curr) 12583 break 12584 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 12585 itr.input.unread(curr) 12586 break 12587 } 12588 12589 // Retrieve the tags on this point for this level of the query. 12590 // This may be different than the bucket dimensions. 12591 tags := curr.Tags.Subset(itr.dims) 12592 id := tags.ID() 12593 12594 // Retrieve the aggregator for this name/tag combination or create one. 12595 rp := m[id] 12596 if rp == nil { 12597 aggregator, emitter := itr.create() 12598 rp = &booleanReduceStringPoint{ 12599 Name: curr.Name, 12600 Tags: tags, 12601 Aggregator: aggregator, 12602 Emitter: emitter, 12603 } 12604 m[id] = rp 12605 } 12606 rp.Aggregator.AggregateBoolean(curr) 12607 } 12608 12609 keys := make([]string, 0, len(m)) 12610 for k := range m { 12611 keys = append(keys, k) 12612 } 12613 12614 // Reverse sort points by name & tag. 12615 // This ensures a consistent order of output. 12616 if len(keys) > 0 { 12617 var sorted sort.Interface = sort.StringSlice(keys) 12618 if itr.opt.Ascending { 12619 sorted = sort.Reverse(sorted) 12620 } 12621 sort.Sort(sorted) 12622 } 12623 12624 // Assume the points are already sorted until proven otherwise. 12625 sortedByTime := true 12626 // Emit the points for each name & tag combination. 12627 a := make([]StringPoint, 0, len(m)) 12628 for _, k := range keys { 12629 rp := m[k] 12630 points := rp.Emitter.Emit() 12631 for i := len(points) - 1; i >= 0; i-- { 12632 points[i].Name = rp.Name 12633 if !itr.keepTags { 12634 points[i].Tags = rp.Tags 12635 } 12636 // Set the points time to the interval time if the reducer didn't provide one. 12637 if points[i].Time == ZeroTime { 12638 points[i].Time = startTime 12639 } else { 12640 sortedByTime = false 12641 } 12642 a = append(a, points[i]) 12643 } 12644 } 12645 // Points may be out of order. Perform a stable sort by time if requested. 12646 if !sortedByTime && itr.opt.Ordered { 12647 var sorted sort.Interface = stringPointsByTime(a) 12648 if itr.opt.Ascending { 12649 sorted = sort.Reverse(sorted) 12650 } 12651 sort.Stable(sorted) 12652 } 12653 return a, nil 12654} 12655 12656// booleanStreamStringIterator streams inputs into the iterator and emits points gradually. 12657type booleanStreamStringIterator struct { 12658 input *bufBooleanIterator 12659 create func() (BooleanPointAggregator, StringPointEmitter) 12660 dims []string 12661 opt IteratorOptions 12662 m map[string]*booleanReduceStringPoint 12663 points []StringPoint 12664} 12665 12666// newBooleanStreamStringIterator returns a new instance of booleanStreamStringIterator. 12667func newBooleanStreamStringIterator(input BooleanIterator, createFn func() (BooleanPointAggregator, StringPointEmitter), opt IteratorOptions) *booleanStreamStringIterator { 12668 return &booleanStreamStringIterator{ 12669 input: newBufBooleanIterator(input), 12670 create: createFn, 12671 dims: opt.GetDimensions(), 12672 opt: opt, 12673 m: make(map[string]*booleanReduceStringPoint), 12674 } 12675} 12676 12677// Stats returns stats from the input iterator. 12678func (itr *booleanStreamStringIterator) Stats() IteratorStats { return itr.input.Stats() } 12679 12680// Close closes the iterator and all child iterators. 12681func (itr *booleanStreamStringIterator) Close() error { return itr.input.Close() } 12682 12683// Next returns the next value for the stream iterator. 12684func (itr *booleanStreamStringIterator) Next() (*StringPoint, error) { 12685 // Calculate next window if we have no more points. 12686 if len(itr.points) == 0 { 12687 var err error 12688 itr.points, err = itr.reduce() 12689 if len(itr.points) == 0 { 12690 return nil, err 12691 } 12692 } 12693 12694 // Pop next point off the stack. 12695 p := &itr.points[len(itr.points)-1] 12696 itr.points = itr.points[:len(itr.points)-1] 12697 return p, nil 12698} 12699 12700// reduce creates and manages aggregators for every point from the input. 12701// After aggregating a point, it always tries to emit a value using the emitter. 12702func (itr *booleanStreamStringIterator) reduce() ([]StringPoint, error) { 12703 // We have already read all of the input points. 12704 if itr.m == nil { 12705 return nil, nil 12706 } 12707 12708 for { 12709 // Read next point. 12710 curr, err := itr.input.Next() 12711 if err != nil { 12712 return nil, err 12713 } else if curr == nil { 12714 // Close all of the aggregators to flush any remaining points to emit. 12715 var points []StringPoint 12716 for _, rp := range itr.m { 12717 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 12718 if err := aggregator.Close(); err != nil { 12719 return nil, err 12720 } 12721 12722 pts := rp.Emitter.Emit() 12723 if len(pts) == 0 { 12724 continue 12725 } 12726 12727 for i := range pts { 12728 pts[i].Name = rp.Name 12729 pts[i].Tags = rp.Tags 12730 } 12731 points = append(points, pts...) 12732 } 12733 } 12734 12735 // Eliminate the aggregators and emitters. 12736 itr.m = nil 12737 return points, nil 12738 } else if curr.Nil { 12739 continue 12740 } 12741 tags := curr.Tags.Subset(itr.dims) 12742 12743 id := curr.Name 12744 if len(tags.m) > 0 { 12745 id += "\x00" + tags.ID() 12746 } 12747 12748 // Retrieve the aggregator for this name/tag combination or create one. 12749 rp := itr.m[id] 12750 if rp == nil { 12751 aggregator, emitter := itr.create() 12752 rp = &booleanReduceStringPoint{ 12753 Name: curr.Name, 12754 Tags: tags, 12755 Aggregator: aggregator, 12756 Emitter: emitter, 12757 } 12758 itr.m[id] = rp 12759 } 12760 rp.Aggregator.AggregateBoolean(curr) 12761 12762 // Attempt to emit points from the aggregator. 12763 points := rp.Emitter.Emit() 12764 if len(points) == 0 { 12765 continue 12766 } 12767 12768 for i := range points { 12769 points[i].Name = rp.Name 12770 points[i].Tags = rp.Tags 12771 } 12772 return points, nil 12773 } 12774} 12775 12776// booleanReduceBooleanIterator executes a reducer for every interval and buffers the result. 12777type booleanReduceBooleanIterator struct { 12778 input *bufBooleanIterator 12779 create func() (BooleanPointAggregator, BooleanPointEmitter) 12780 dims []string 12781 opt IteratorOptions 12782 points []BooleanPoint 12783 keepTags bool 12784} 12785 12786func newBooleanReduceBooleanIterator(input BooleanIterator, opt IteratorOptions, createFn func() (BooleanPointAggregator, BooleanPointEmitter)) *booleanReduceBooleanIterator { 12787 return &booleanReduceBooleanIterator{ 12788 input: newBufBooleanIterator(input), 12789 create: createFn, 12790 dims: opt.GetDimensions(), 12791 opt: opt, 12792 } 12793} 12794 12795// Stats returns stats from the input iterator. 12796func (itr *booleanReduceBooleanIterator) Stats() IteratorStats { return itr.input.Stats() } 12797 12798// Close closes the iterator and all child iterators. 12799func (itr *booleanReduceBooleanIterator) Close() error { return itr.input.Close() } 12800 12801// Next returns the minimum value for the next available interval. 12802func (itr *booleanReduceBooleanIterator) Next() (*BooleanPoint, error) { 12803 // Calculate next window if we have no more points. 12804 if len(itr.points) == 0 { 12805 var err error 12806 itr.points, err = itr.reduce() 12807 if len(itr.points) == 0 { 12808 return nil, err 12809 } 12810 } 12811 12812 // Pop next point off the stack. 12813 p := &itr.points[len(itr.points)-1] 12814 itr.points = itr.points[:len(itr.points)-1] 12815 return p, nil 12816} 12817 12818// booleanReduceBooleanPoint stores the reduced data for a name/tag combination. 12819type booleanReduceBooleanPoint struct { 12820 Name string 12821 Tags Tags 12822 Aggregator BooleanPointAggregator 12823 Emitter BooleanPointEmitter 12824} 12825 12826// reduce executes fn once for every point in the next window. 12827// The previous value for the dimension is passed to fn. 12828func (itr *booleanReduceBooleanIterator) reduce() ([]BooleanPoint, error) { 12829 // Calculate next window. 12830 var ( 12831 startTime, endTime int64 12832 window struct { 12833 name string 12834 tags string 12835 } 12836 ) 12837 for { 12838 p, err := itr.input.Next() 12839 if err != nil || p == nil { 12840 return nil, err 12841 } else if p.Nil { 12842 continue 12843 } 12844 12845 // Unread the point so it can be processed. 12846 itr.input.unread(p) 12847 startTime, endTime = itr.opt.Window(p.Time) 12848 window.name, window.tags = p.Name, p.Tags.Subset(itr.opt.Dimensions).ID() 12849 break 12850 } 12851 12852 // Create points by tags. 12853 m := make(map[string]*booleanReduceBooleanPoint) 12854 for { 12855 // Read next point. 12856 curr, err := itr.input.NextInWindow(startTime, endTime) 12857 if err != nil { 12858 return nil, err 12859 } else if curr == nil { 12860 break 12861 } else if curr.Nil { 12862 continue 12863 } else if curr.Name != window.name { 12864 itr.input.unread(curr) 12865 break 12866 } 12867 12868 // Ensure this point is within the same final window. 12869 if curr.Name != window.name { 12870 itr.input.unread(curr) 12871 break 12872 } else if tags := curr.Tags.Subset(itr.opt.Dimensions); tags.ID() != window.tags { 12873 itr.input.unread(curr) 12874 break 12875 } 12876 12877 // Retrieve the tags on this point for this level of the query. 12878 // This may be different than the bucket dimensions. 12879 tags := curr.Tags.Subset(itr.dims) 12880 id := tags.ID() 12881 12882 // Retrieve the aggregator for this name/tag combination or create one. 12883 rp := m[id] 12884 if rp == nil { 12885 aggregator, emitter := itr.create() 12886 rp = &booleanReduceBooleanPoint{ 12887 Name: curr.Name, 12888 Tags: tags, 12889 Aggregator: aggregator, 12890 Emitter: emitter, 12891 } 12892 m[id] = rp 12893 } 12894 rp.Aggregator.AggregateBoolean(curr) 12895 } 12896 12897 keys := make([]string, 0, len(m)) 12898 for k := range m { 12899 keys = append(keys, k) 12900 } 12901 12902 // Reverse sort points by name & tag. 12903 // This ensures a consistent order of output. 12904 if len(keys) > 0 { 12905 var sorted sort.Interface = sort.StringSlice(keys) 12906 if itr.opt.Ascending { 12907 sorted = sort.Reverse(sorted) 12908 } 12909 sort.Sort(sorted) 12910 } 12911 12912 // Assume the points are already sorted until proven otherwise. 12913 sortedByTime := true 12914 // Emit the points for each name & tag combination. 12915 a := make([]BooleanPoint, 0, len(m)) 12916 for _, k := range keys { 12917 rp := m[k] 12918 points := rp.Emitter.Emit() 12919 for i := len(points) - 1; i >= 0; i-- { 12920 points[i].Name = rp.Name 12921 if !itr.keepTags { 12922 points[i].Tags = rp.Tags 12923 } 12924 // Set the points time to the interval time if the reducer didn't provide one. 12925 if points[i].Time == ZeroTime { 12926 points[i].Time = startTime 12927 } else { 12928 sortedByTime = false 12929 } 12930 a = append(a, points[i]) 12931 } 12932 } 12933 // Points may be out of order. Perform a stable sort by time if requested. 12934 if !sortedByTime && itr.opt.Ordered { 12935 var sorted sort.Interface = booleanPointsByTime(a) 12936 if itr.opt.Ascending { 12937 sorted = sort.Reverse(sorted) 12938 } 12939 sort.Stable(sorted) 12940 } 12941 return a, nil 12942} 12943 12944// booleanStreamBooleanIterator streams inputs into the iterator and emits points gradually. 12945type booleanStreamBooleanIterator struct { 12946 input *bufBooleanIterator 12947 create func() (BooleanPointAggregator, BooleanPointEmitter) 12948 dims []string 12949 opt IteratorOptions 12950 m map[string]*booleanReduceBooleanPoint 12951 points []BooleanPoint 12952} 12953 12954// newBooleanStreamBooleanIterator returns a new instance of booleanStreamBooleanIterator. 12955func newBooleanStreamBooleanIterator(input BooleanIterator, createFn func() (BooleanPointAggregator, BooleanPointEmitter), opt IteratorOptions) *booleanStreamBooleanIterator { 12956 return &booleanStreamBooleanIterator{ 12957 input: newBufBooleanIterator(input), 12958 create: createFn, 12959 dims: opt.GetDimensions(), 12960 opt: opt, 12961 m: make(map[string]*booleanReduceBooleanPoint), 12962 } 12963} 12964 12965// Stats returns stats from the input iterator. 12966func (itr *booleanStreamBooleanIterator) Stats() IteratorStats { return itr.input.Stats() } 12967 12968// Close closes the iterator and all child iterators. 12969func (itr *booleanStreamBooleanIterator) Close() error { return itr.input.Close() } 12970 12971// Next returns the next value for the stream iterator. 12972func (itr *booleanStreamBooleanIterator) Next() (*BooleanPoint, error) { 12973 // Calculate next window if we have no more points. 12974 if len(itr.points) == 0 { 12975 var err error 12976 itr.points, err = itr.reduce() 12977 if len(itr.points) == 0 { 12978 return nil, err 12979 } 12980 } 12981 12982 // Pop next point off the stack. 12983 p := &itr.points[len(itr.points)-1] 12984 itr.points = itr.points[:len(itr.points)-1] 12985 return p, nil 12986} 12987 12988// reduce creates and manages aggregators for every point from the input. 12989// After aggregating a point, it always tries to emit a value using the emitter. 12990func (itr *booleanStreamBooleanIterator) reduce() ([]BooleanPoint, error) { 12991 // We have already read all of the input points. 12992 if itr.m == nil { 12993 return nil, nil 12994 } 12995 12996 for { 12997 // Read next point. 12998 curr, err := itr.input.Next() 12999 if err != nil { 13000 return nil, err 13001 } else if curr == nil { 13002 // Close all of the aggregators to flush any remaining points to emit. 13003 var points []BooleanPoint 13004 for _, rp := range itr.m { 13005 if aggregator, ok := rp.Aggregator.(io.Closer); ok { 13006 if err := aggregator.Close(); err != nil { 13007 return nil, err 13008 } 13009 13010 pts := rp.Emitter.Emit() 13011 if len(pts) == 0 { 13012 continue 13013 } 13014 13015 for i := range pts { 13016 pts[i].Name = rp.Name 13017 pts[i].Tags = rp.Tags 13018 } 13019 points = append(points, pts...) 13020 } 13021 } 13022 13023 // Eliminate the aggregators and emitters. 13024 itr.m = nil 13025 return points, nil 13026 } else if curr.Nil { 13027 continue 13028 } 13029 tags := curr.Tags.Subset(itr.dims) 13030 13031 id := curr.Name 13032 if len(tags.m) > 0 { 13033 id += "\x00" + tags.ID() 13034 } 13035 13036 // Retrieve the aggregator for this name/tag combination or create one. 13037 rp := itr.m[id] 13038 if rp == nil { 13039 aggregator, emitter := itr.create() 13040 rp = &booleanReduceBooleanPoint{ 13041 Name: curr.Name, 13042 Tags: tags, 13043 Aggregator: aggregator, 13044 Emitter: emitter, 13045 } 13046 itr.m[id] = rp 13047 } 13048 rp.Aggregator.AggregateBoolean(curr) 13049 13050 // Attempt to emit points from the aggregator. 13051 points := rp.Emitter.Emit() 13052 if len(points) == 0 { 13053 continue 13054 } 13055 13056 for i := range points { 13057 points[i].Name = rp.Name 13058 points[i].Tags = rp.Tags 13059 } 13060 return points, nil 13061 } 13062} 13063 13064// booleanDedupeIterator only outputs unique points. 13065// This differs from the DistinctIterator in that it compares all aux fields too. 13066// This iterator is relatively inefficient and should only be used on small 13067// datasets such as meta query results. 13068type booleanDedupeIterator struct { 13069 input BooleanIterator 13070 m map[string]struct{} // lookup of points already sent 13071} 13072 13073type booleanIteratorMapper struct { 13074 cur Cursor 13075 row Row 13076 driver IteratorMap // which iterator to use for the primary value, can be nil 13077 fields []IteratorMap // which iterator to use for an aux field 13078 point BooleanPoint 13079} 13080 13081func newBooleanIteratorMapper(cur Cursor, driver IteratorMap, fields []IteratorMap, opt IteratorOptions) *booleanIteratorMapper { 13082 return &booleanIteratorMapper{ 13083 cur: cur, 13084 driver: driver, 13085 fields: fields, 13086 point: BooleanPoint{ 13087 Aux: make([]interface{}, len(fields)), 13088 }, 13089 } 13090} 13091 13092func (itr *booleanIteratorMapper) Next() (*BooleanPoint, error) { 13093 if !itr.cur.Scan(&itr.row) { 13094 if err := itr.cur.Err(); err != nil { 13095 return nil, err 13096 } 13097 return nil, nil 13098 } 13099 13100 itr.point.Time = itr.row.Time 13101 itr.point.Name = itr.row.Series.Name 13102 itr.point.Tags = itr.row.Series.Tags 13103 13104 if itr.driver != nil { 13105 if v := itr.driver.Value(&itr.row); v != nil { 13106 if v, ok := castToBoolean(v); ok { 13107 itr.point.Value = v 13108 itr.point.Nil = false 13109 } else { 13110 itr.point.Value = false 13111 itr.point.Nil = true 13112 } 13113 } else { 13114 itr.point.Value = false 13115 itr.point.Nil = true 13116 } 13117 } 13118 for i, f := range itr.fields { 13119 itr.point.Aux[i] = f.Value(&itr.row) 13120 } 13121 return &itr.point, nil 13122} 13123 13124func (itr *booleanIteratorMapper) Stats() IteratorStats { 13125 return itr.cur.Stats() 13126} 13127 13128func (itr *booleanIteratorMapper) Close() error { 13129 return itr.cur.Close() 13130} 13131 13132type booleanFilterIterator struct { 13133 input BooleanIterator 13134 cond influxql.Expr 13135 opt IteratorOptions 13136 m map[string]interface{} 13137} 13138 13139func newBooleanFilterIterator(input BooleanIterator, cond influxql.Expr, opt IteratorOptions) BooleanIterator { 13140 // Strip out time conditions from the WHERE clause. 13141 // TODO(jsternberg): This should really be done for us when creating the IteratorOptions struct. 13142 n := influxql.RewriteFunc(influxql.CloneExpr(cond), func(n influxql.Node) influxql.Node { 13143 switch n := n.(type) { 13144 case *influxql.BinaryExpr: 13145 if n.LHS.String() == "time" { 13146 return &influxql.BooleanLiteral{Val: true} 13147 } 13148 } 13149 return n 13150 }) 13151 13152 cond, _ = n.(influxql.Expr) 13153 if cond == nil { 13154 return input 13155 } else if n, ok := cond.(*influxql.BooleanLiteral); ok && n.Val { 13156 return input 13157 } 13158 13159 return &booleanFilterIterator{ 13160 input: input, 13161 cond: cond, 13162 opt: opt, 13163 m: make(map[string]interface{}), 13164 } 13165} 13166 13167func (itr *booleanFilterIterator) Stats() IteratorStats { return itr.input.Stats() } 13168func (itr *booleanFilterIterator) Close() error { return itr.input.Close() } 13169 13170func (itr *booleanFilterIterator) Next() (*BooleanPoint, error) { 13171 for { 13172 p, err := itr.input.Next() 13173 if err != nil || p == nil { 13174 return nil, err 13175 } 13176 13177 for i, ref := range itr.opt.Aux { 13178 itr.m[ref.Val] = p.Aux[i] 13179 } 13180 for k, v := range p.Tags.KeyValues() { 13181 itr.m[k] = v 13182 } 13183 13184 if !influxql.EvalBool(itr.cond, itr.m) { 13185 continue 13186 } 13187 return p, nil 13188 } 13189} 13190 13191type booleanTagSubsetIterator struct { 13192 input BooleanIterator 13193 point BooleanPoint 13194 lastTags Tags 13195 dimensions []string 13196} 13197 13198func newBooleanTagSubsetIterator(input BooleanIterator, opt IteratorOptions) *booleanTagSubsetIterator { 13199 return &booleanTagSubsetIterator{ 13200 input: input, 13201 dimensions: opt.GetDimensions(), 13202 } 13203} 13204 13205func (itr *booleanTagSubsetIterator) Next() (*BooleanPoint, error) { 13206 p, err := itr.input.Next() 13207 if err != nil { 13208 return nil, err 13209 } else if p == nil { 13210 return nil, nil 13211 } 13212 13213 itr.point.Name = p.Name 13214 if !p.Tags.Equal(itr.lastTags) { 13215 itr.point.Tags = p.Tags.Subset(itr.dimensions) 13216 itr.lastTags = p.Tags 13217 } 13218 itr.point.Time = p.Time 13219 itr.point.Value = p.Value 13220 itr.point.Aux = p.Aux 13221 itr.point.Aggregated = p.Aggregated 13222 itr.point.Nil = p.Nil 13223 return &itr.point, nil 13224} 13225 13226func (itr *booleanTagSubsetIterator) Stats() IteratorStats { 13227 return itr.input.Stats() 13228} 13229 13230func (itr *booleanTagSubsetIterator) Close() error { 13231 return itr.input.Close() 13232} 13233 13234// newBooleanDedupeIterator returns a new instance of booleanDedupeIterator. 13235func newBooleanDedupeIterator(input BooleanIterator) *booleanDedupeIterator { 13236 return &booleanDedupeIterator{ 13237 input: input, 13238 m: make(map[string]struct{}), 13239 } 13240} 13241 13242// Stats returns stats from the input iterator. 13243func (itr *booleanDedupeIterator) Stats() IteratorStats { return itr.input.Stats() } 13244 13245// Close closes the iterator and all child iterators. 13246func (itr *booleanDedupeIterator) Close() error { return itr.input.Close() } 13247 13248// Next returns the next unique point from the input iterator. 13249func (itr *booleanDedupeIterator) Next() (*BooleanPoint, error) { 13250 for { 13251 // Read next point. 13252 p, err := itr.input.Next() 13253 if p == nil || err != nil { 13254 return nil, err 13255 } 13256 13257 // Serialize to bytes to store in lookup. 13258 buf, err := proto.Marshal(encodeBooleanPoint(p)) 13259 if err != nil { 13260 return nil, err 13261 } 13262 13263 // If the point has already been output then move to the next point. 13264 if _, ok := itr.m[string(buf)]; ok { 13265 continue 13266 } 13267 13268 // Otherwise mark it as emitted and return point. 13269 itr.m[string(buf)] = struct{}{} 13270 return p, nil 13271 } 13272} 13273 13274// booleanReaderIterator represents an iterator that streams from a reader. 13275type booleanReaderIterator struct { 13276 r io.Reader 13277 dec *BooleanPointDecoder 13278} 13279 13280// newBooleanReaderIterator returns a new instance of booleanReaderIterator. 13281func newBooleanReaderIterator(ctx context.Context, r io.Reader, stats IteratorStats) *booleanReaderIterator { 13282 dec := NewBooleanPointDecoder(ctx, r) 13283 dec.stats = stats 13284 13285 return &booleanReaderIterator{ 13286 r: r, 13287 dec: dec, 13288 } 13289} 13290 13291// Stats returns stats about points processed. 13292func (itr *booleanReaderIterator) Stats() IteratorStats { return itr.dec.stats } 13293 13294// Close closes the underlying reader, if applicable. 13295func (itr *booleanReaderIterator) Close() error { 13296 if r, ok := itr.r.(io.ReadCloser); ok { 13297 return r.Close() 13298 } 13299 return nil 13300} 13301 13302// Next returns the next point from the iterator. 13303func (itr *booleanReaderIterator) Next() (*BooleanPoint, error) { 13304 // OPTIMIZE(benbjohnson): Reuse point on iterator. 13305 13306 // Unmarshal next point. 13307 p := &BooleanPoint{} 13308 if err := itr.dec.DecodeBooleanPoint(p); err == io.EOF { 13309 return nil, nil 13310 } else if err != nil { 13311 return nil, err 13312 } 13313 return p, nil 13314} 13315 13316// encodeFloatIterator encodes all points from itr to the underlying writer. 13317func (enc *IteratorEncoder) encodeFloatIterator(itr FloatIterator) error { 13318 ticker := time.NewTicker(enc.StatsInterval) 13319 defer ticker.Stop() 13320 13321 // Emit initial stats. 13322 if err := enc.encodeStats(itr.Stats()); err != nil { 13323 return err 13324 } 13325 13326 // Continually stream points from the iterator into the encoder. 13327 penc := NewFloatPointEncoder(enc.w) 13328 for { 13329 // Emit stats periodically. 13330 select { 13331 case <-ticker.C: 13332 if err := enc.encodeStats(itr.Stats()); err != nil { 13333 return err 13334 } 13335 default: 13336 } 13337 13338 // Retrieve the next point from the iterator. 13339 p, err := itr.Next() 13340 if err != nil { 13341 return err 13342 } else if p == nil { 13343 break 13344 } 13345 13346 // Write the point to the point encoder. 13347 if err := penc.EncodeFloatPoint(p); err != nil { 13348 return err 13349 } 13350 } 13351 13352 // Emit final stats. 13353 if err := enc.encodeStats(itr.Stats()); err != nil { 13354 return err 13355 } 13356 return nil 13357} 13358 13359// encodeIntegerIterator encodes all points from itr to the underlying writer. 13360func (enc *IteratorEncoder) encodeIntegerIterator(itr IntegerIterator) error { 13361 ticker := time.NewTicker(enc.StatsInterval) 13362 defer ticker.Stop() 13363 13364 // Emit initial stats. 13365 if err := enc.encodeStats(itr.Stats()); err != nil { 13366 return err 13367 } 13368 13369 // Continually stream points from the iterator into the encoder. 13370 penc := NewIntegerPointEncoder(enc.w) 13371 for { 13372 // Emit stats periodically. 13373 select { 13374 case <-ticker.C: 13375 if err := enc.encodeStats(itr.Stats()); err != nil { 13376 return err 13377 } 13378 default: 13379 } 13380 13381 // Retrieve the next point from the iterator. 13382 p, err := itr.Next() 13383 if err != nil { 13384 return err 13385 } else if p == nil { 13386 break 13387 } 13388 13389 // Write the point to the point encoder. 13390 if err := penc.EncodeIntegerPoint(p); err != nil { 13391 return err 13392 } 13393 } 13394 13395 // Emit final stats. 13396 if err := enc.encodeStats(itr.Stats()); err != nil { 13397 return err 13398 } 13399 return nil 13400} 13401 13402// encodeUnsignedIterator encodes all points from itr to the underlying writer. 13403func (enc *IteratorEncoder) encodeUnsignedIterator(itr UnsignedIterator) error { 13404 ticker := time.NewTicker(enc.StatsInterval) 13405 defer ticker.Stop() 13406 13407 // Emit initial stats. 13408 if err := enc.encodeStats(itr.Stats()); err != nil { 13409 return err 13410 } 13411 13412 // Continually stream points from the iterator into the encoder. 13413 penc := NewUnsignedPointEncoder(enc.w) 13414 for { 13415 // Emit stats periodically. 13416 select { 13417 case <-ticker.C: 13418 if err := enc.encodeStats(itr.Stats()); err != nil { 13419 return err 13420 } 13421 default: 13422 } 13423 13424 // Retrieve the next point from the iterator. 13425 p, err := itr.Next() 13426 if err != nil { 13427 return err 13428 } else if p == nil { 13429 break 13430 } 13431 13432 // Write the point to the point encoder. 13433 if err := penc.EncodeUnsignedPoint(p); err != nil { 13434 return err 13435 } 13436 } 13437 13438 // Emit final stats. 13439 if err := enc.encodeStats(itr.Stats()); err != nil { 13440 return err 13441 } 13442 return nil 13443} 13444 13445// encodeStringIterator encodes all points from itr to the underlying writer. 13446func (enc *IteratorEncoder) encodeStringIterator(itr StringIterator) error { 13447 ticker := time.NewTicker(enc.StatsInterval) 13448 defer ticker.Stop() 13449 13450 // Emit initial stats. 13451 if err := enc.encodeStats(itr.Stats()); err != nil { 13452 return err 13453 } 13454 13455 // Continually stream points from the iterator into the encoder. 13456 penc := NewStringPointEncoder(enc.w) 13457 for { 13458 // Emit stats periodically. 13459 select { 13460 case <-ticker.C: 13461 if err := enc.encodeStats(itr.Stats()); err != nil { 13462 return err 13463 } 13464 default: 13465 } 13466 13467 // Retrieve the next point from the iterator. 13468 p, err := itr.Next() 13469 if err != nil { 13470 return err 13471 } else if p == nil { 13472 break 13473 } 13474 13475 // Write the point to the point encoder. 13476 if err := penc.EncodeStringPoint(p); err != nil { 13477 return err 13478 } 13479 } 13480 13481 // Emit final stats. 13482 if err := enc.encodeStats(itr.Stats()); err != nil { 13483 return err 13484 } 13485 return nil 13486} 13487 13488// encodeBooleanIterator encodes all points from itr to the underlying writer. 13489func (enc *IteratorEncoder) encodeBooleanIterator(itr BooleanIterator) error { 13490 ticker := time.NewTicker(enc.StatsInterval) 13491 defer ticker.Stop() 13492 13493 // Emit initial stats. 13494 if err := enc.encodeStats(itr.Stats()); err != nil { 13495 return err 13496 } 13497 13498 // Continually stream points from the iterator into the encoder. 13499 penc := NewBooleanPointEncoder(enc.w) 13500 for { 13501 // Emit stats periodically. 13502 select { 13503 case <-ticker.C: 13504 if err := enc.encodeStats(itr.Stats()); err != nil { 13505 return err 13506 } 13507 default: 13508 } 13509 13510 // Retrieve the next point from the iterator. 13511 p, err := itr.Next() 13512 if err != nil { 13513 return err 13514 } else if p == nil { 13515 break 13516 } 13517 13518 // Write the point to the point encoder. 13519 if err := penc.EncodeBooleanPoint(p); err != nil { 13520 return err 13521 } 13522 } 13523 13524 // Emit final stats. 13525 if err := enc.encodeStats(itr.Stats()); err != nil { 13526 return err 13527 } 13528 return nil 13529} 13530