github.com/m3db/m3@v1.5.0/src/m3ninx/index/segment/fst/fst_terms_postings_iterator.go (about)

     1  // Copyright (c) 2018 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 fst
    22  
    23  import (
    24  	"github.com/m3db/m3/src/m3ninx/generated/proto/fswriter"
    25  	sgmt "github.com/m3db/m3/src/m3ninx/index/segment"
    26  	"github.com/m3db/m3/src/m3ninx/postings"
    27  	postingsroaring "github.com/m3db/m3/src/m3ninx/postings/roaring"
    28  	"github.com/m3dbx/pilosa/roaring"
    29  )
    30  
    31  // postingsIterRoaringPoolingConfig uses a configuration that avoids allocating
    32  // any containers in the roaring bitmap, since these roaring bitmaps are backed
    33  // by mmaps and don't have any native containers themselves.
    34  var postingsIterRoaringPoolingConfig = roaring.ContainerPoolingConfiguration{
    35  	MaxArraySize:                    0,
    36  	MaxRunsSize:                     0,
    37  	AllocateBitmap:                  false,
    38  	MaxCapacity:                     0,
    39  	MaxKeysAndContainersSliceLength: 128 * 10,
    40  }
    41  
    42  type fstTermsPostingsIter struct {
    43  	bitmap   *roaring.Bitmap
    44  	postings postings.List
    45  
    46  	seg       *fsSegment
    47  	termsIter *fstTermsIter
    48  	currTerm  []byte
    49  	err       error
    50  }
    51  
    52  func newFSTTermsPostingsIter() *fstTermsPostingsIter {
    53  	bitmap := roaring.NewBitmapWithPooling(postingsIterRoaringPoolingConfig)
    54  	i := &fstTermsPostingsIter{
    55  		bitmap:   bitmap,
    56  		postings: postingsroaring.NewPostingsListFromBitmap(bitmap),
    57  	}
    58  	i.clear()
    59  	return i
    60  }
    61  
    62  var _ sgmt.TermsIterator = &fstTermsPostingsIter{}
    63  
    64  func (f *fstTermsPostingsIter) clear() {
    65  	f.bitmap.Reset()
    66  	f.seg = nil
    67  	f.termsIter = nil
    68  	f.currTerm = nil
    69  	f.err = nil
    70  }
    71  
    72  func (f *fstTermsPostingsIter) reset(
    73  	seg *fsSegment,
    74  	termsIter *fstTermsIter,
    75  ) {
    76  	f.clear()
    77  
    78  	f.seg = seg
    79  	f.termsIter = termsIter
    80  }
    81  
    82  func (f *fstTermsPostingsIter) Empty() bool {
    83  	return f.termsIter.Empty()
    84  }
    85  
    86  func (f *fstTermsPostingsIter) Next() bool {
    87  	if f.err != nil {
    88  		return false
    89  	}
    90  
    91  	next := f.termsIter.Next()
    92  	if !next {
    93  		return false
    94  	}
    95  
    96  	f.currTerm = f.termsIter.Current()
    97  	currOffset := f.termsIter.CurrentOffset()
    98  
    99  	f.seg.RLock()
   100  	if f.termsIter.opts.fieldsFST {
   101  		var fieldsData fswriter.FieldData
   102  		fieldsData, f.err = f.seg.unmarshalFieldDataNotClosedMaybeFinalizedWithRLock(currOffset)
   103  		currOffset = fieldsData.FieldPostingsListOffset
   104  	}
   105  	if f.err == nil {
   106  		// Only attempt if the previous unmarshal definitely succeeded
   107  		// if we are operating on a fields FST.
   108  		f.err = f.seg.unmarshalPostingsListBitmapNotClosedMaybeFinalizedWithLock(f.bitmap,
   109  			currOffset)
   110  	}
   111  	f.seg.RUnlock()
   112  
   113  	return f.err == nil
   114  }
   115  
   116  func (f *fstTermsPostingsIter) Current() ([]byte, postings.List) {
   117  	return f.currTerm, f.postings
   118  }
   119  
   120  func (f *fstTermsPostingsIter) Err() error {
   121  	return f.err
   122  }
   123  
   124  func (f *fstTermsPostingsIter) Close() error {
   125  	var err error
   126  	if f.termsIter != nil {
   127  		err = f.termsIter.Close()
   128  	}
   129  	f.clear()
   130  	return err
   131  }