github.com/m3db/m3@v1.5.0/src/dbnode/storage/index/aggregate_iter.go (about)

     1  // Copyright (c) 2021 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package index
    22  
    23  import (
    24  	"github.com/m3db/m3/src/m3ninx/index/segment"
    25  	"github.com/m3db/m3/src/x/context"
    26  	xerrors "github.com/m3db/m3/src/x/errors"
    27  )
    28  
    29  var _ AggregateIterator = &aggregateIter{}
    30  
    31  type aggregateIter struct {
    32  	// immutable state
    33  	readers     []segment.Reader
    34  	iterateOpts fieldsAndTermsIteratorOpts
    35  	newIterFn   newFieldsAndTermsIteratorFn
    36  
    37  	// immutable state after first Next() call
    38  	iters []fieldsAndTermsIterator
    39  
    40  	// mutable state
    41  	idx                    int
    42  	err                    error
    43  	done                   bool
    44  	currField, currTerm    []byte
    45  	nextField, nextTerm    []byte
    46  	docsCount, seriesCount int
    47  }
    48  
    49  func (it *aggregateIter) Next(ctx context.Context) bool {
    50  	if it.Done() {
    51  		return false
    52  	}
    53  	if it.iters == nil {
    54  		for _, reader := range it.readers {
    55  			iter, err := it.newIterFn(ctx, reader, it.iterateOpts)
    56  			if err != nil {
    57  				it.err = err
    58  				return false
    59  			}
    60  			it.iters = append(it.iters, iter)
    61  		}
    62  		if !it.next() {
    63  			it.done = true
    64  			return false
    65  		}
    66  		it.nextField, it.nextTerm = it.current()
    67  	}
    68  	// the fieldAndTermsIterator mutates the underlying byte slice, so we need to copy to preserve the value.
    69  	it.currField = append(it.currField[:0], it.nextField...)
    70  	it.currTerm = append(it.currTerm[:0], it.nextTerm...)
    71  
    72  	if it.next() {
    73  		it.nextField, it.nextTerm = it.current()
    74  	} else {
    75  		// the iterators have been exhausted. mark done so the next call Done returns true. Still return true from
    76  		// this call so the caller can retrieve the last element with Current.
    77  		it.done = true
    78  	}
    79  	return true
    80  }
    81  
    82  func (it *aggregateIter) next() bool {
    83  	if it.idx == len(it.iters) {
    84  		return false
    85  	}
    86  	currIter := it.iters[it.idx]
    87  
    88  	for !currIter.Next() {
    89  		if err := currIter.Err(); err != nil {
    90  			it.err = err
    91  			return false
    92  		}
    93  		// move to next iterator so we don't try to Close twice.
    94  		it.idx++
    95  
    96  		if err := currIter.Close(); err != nil {
    97  			it.err = err
    98  			return false
    99  		}
   100  
   101  		if it.idx == len(it.iters) {
   102  			return false
   103  		}
   104  		currIter = it.iters[it.idx]
   105  	}
   106  	return true
   107  }
   108  
   109  func (it *aggregateIter) current() (field, term []byte) {
   110  	return it.iters[it.idx].Current()
   111  }
   112  
   113  func (it *aggregateIter) Err() error {
   114  	return it.err
   115  }
   116  
   117  func (it *aggregateIter) Done() bool {
   118  	return it.err != nil || it.done
   119  }
   120  
   121  func (it *aggregateIter) Current() (field, term []byte) {
   122  	return it.currField, it.currTerm
   123  }
   124  
   125  func (it *aggregateIter) fieldsAndTermsIteratorOpts() fieldsAndTermsIteratorOpts {
   126  	return it.iterateOpts
   127  }
   128  
   129  func (it *aggregateIter) Close() error {
   130  	if it.iters == nil {
   131  		return nil
   132  	}
   133  	var multiErr xerrors.MultiError
   134  	// close any iterators that weren't closed in Next.
   135  	for i := it.idx; i < len(it.iters); i++ {
   136  		multiErr = multiErr.Add(it.iters[i].Close())
   137  	}
   138  	return multiErr.FinalError()
   139  }
   140  
   141  func (it *aggregateIter) AddSeries(count int) {
   142  	it.seriesCount += count
   143  }
   144  
   145  func (it *aggregateIter) AddDocs(count int) {
   146  	it.docsCount += count
   147  }
   148  
   149  func (it *aggregateIter) Counts() (series, docs int) {
   150  	return it.seriesCount, it.docsCount
   151  }