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 }