github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/core/store/multiLevelSkipListWriter.go (about)

     1  package store
     2  
     3  import (
     4  	"github.com/balzaczyy/golucene/core/util"
     5  )
     6  
     7  type MultiLevelSkipListWriterSPI interface {
     8  	WriteSkipData(level int, skipBuffer IndexOutput) error
     9  }
    10  
    11  /*
    12  TODO: migrate original comment.
    13  
    14  Note: this class was moved from package codec to store since it
    15  caused cyclic dependency (store<->codec).
    16  */
    17  type MultiLevelSkipListWriter struct {
    18  	spi MultiLevelSkipListWriterSPI
    19  	// number levels in this skip list
    20  	numberOfSkipLevels int
    21  	// the skip interval in ths list with level=0
    22  	skipInterval int
    23  	// skipInterval used for level > 0
    24  	skipMultiplier int
    25  	// for every skip level a different buffer is used
    26  	skipBuffer []*RAMOutputStream
    27  }
    28  
    29  /* Creates a MultiLevelSkipListWriter. */
    30  func NewMultiLevelSkipListWriter(spi MultiLevelSkipListWriterSPI,
    31  	skipInterval, skipMultiplier, maxSkipLevels, df int) *MultiLevelSkipListWriter {
    32  
    33  	numberOfSkipLevels := 1
    34  	// calculate the maximum number of skip levels for this document frequency
    35  	if df > skipInterval {
    36  		numberOfSkipLevels = 1 + util.Log(int64(df/skipInterval), skipMultiplier)
    37  	}
    38  	// make sure it does not exceed maxSkipLevels
    39  	if numberOfSkipLevels > maxSkipLevels {
    40  		numberOfSkipLevels = maxSkipLevels
    41  	}
    42  	return &MultiLevelSkipListWriter{
    43  		spi:                spi,
    44  		skipInterval:       skipInterval,
    45  		skipMultiplier:     skipMultiplier,
    46  		numberOfSkipLevels: numberOfSkipLevels,
    47  	}
    48  }
    49  
    50  /* Allocates internal skip buffers. */
    51  func (w *MultiLevelSkipListWriter) init() {
    52  	w.skipBuffer = make([]*RAMOutputStream, w.numberOfSkipLevels)
    53  	for i, _ := range w.skipBuffer {
    54  		w.skipBuffer[i] = NewRAMOutputStreamBuffer()
    55  	}
    56  }
    57  
    58  /* Creates new buffers or empties the existing ones */
    59  func (w *MultiLevelSkipListWriter) ResetSkip() {
    60  	if w.skipBuffer == nil {
    61  		w.init()
    62  	} else {
    63  		for _, v := range w.skipBuffer {
    64  			v.Reset()
    65  		}
    66  	}
    67  }
    68  
    69  /*
    70  Writes the current skip data to the buffers. The current document
    71  frequency determines the max level is skip ddata is to be written to.
    72  */
    73  func (w *MultiLevelSkipListWriter) BufferSkip(df int) error {
    74  	assert(df%w.skipInterval == 0)
    75  	numLevels := 1
    76  	df /= w.skipInterval
    77  
    78  	// determine max level
    79  	for (df%w.skipMultiplier) == 0 && numLevels < w.numberOfSkipLevels {
    80  		numLevels++
    81  		df /= w.skipMultiplier
    82  	}
    83  
    84  	childPointer := int64(0)
    85  
    86  	var err error
    87  	for level := 0; level < numLevels; level++ {
    88  		if err = w.spi.WriteSkipData(level, w.skipBuffer[level]); err != nil {
    89  			return err
    90  		}
    91  
    92  		newChildPointer := w.skipBuffer[level].FilePointer()
    93  
    94  		if level != 0 {
    95  			// store child pointers for all levels except the lowest
    96  			if err = w.skipBuffer[level].WriteVLong(childPointer); err != nil {
    97  				return err
    98  			}
    99  		}
   100  
   101  		// remember the childPointer for the next level
   102  		childPointer = newChildPointer
   103  	}
   104  	return nil
   105  }
   106  
   107  /* Writes the buffered skip lists to the given output. */
   108  func (w *MultiLevelSkipListWriter) WriteSkip(output IndexOutput) (int64, error) {
   109  	skipPointer := output.FilePointer()
   110  	if len(w.skipBuffer) == 0 {
   111  		return skipPointer, nil
   112  	}
   113  
   114  	for level := w.numberOfSkipLevels - 1; level > 0; level-- {
   115  		if length := w.skipBuffer[level].FilePointer(); length > 0 {
   116  			err := output.WriteVLong(length)
   117  			if err != nil {
   118  				return 0, err
   119  			}
   120  			err = w.skipBuffer[level].WriteTo(output)
   121  			if err != nil {
   122  				return 0, err
   123  			}
   124  		}
   125  	}
   126  	return skipPointer, w.skipBuffer[0].WriteTo(output)
   127  }