github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/core/codec/lucene46/fieldInfos.go (about) 1 package lucene46 2 3 import ( 4 "errors" 5 "fmt" 6 "github.com/balzaczyy/golucene/core/codec" 7 . "github.com/balzaczyy/golucene/core/codec/spi" 8 . "github.com/balzaczyy/golucene/core/index/model" 9 "github.com/balzaczyy/golucene/core/store" 10 "github.com/balzaczyy/golucene/core/util" 11 ) 12 13 // lucene46/Lucene46FieldInfosFormat.java 14 15 const ( 16 /* Extension of field info */ 17 FI_EXTENSION = "fnm" 18 19 /* Codec header */ 20 FI_CODEC_NAME = "Lucene46FieldInfos" 21 FI_FORMAT_START = 0 22 FI_FORMAT_CHECKSUM = 1 23 FI_FORMAT_SORTED_NUMERIC = 2 24 FI_FORMAT_CURRENT = FI_FORMAT_SORTED_NUMERIC 25 26 // Field flags 27 FI_IS_INDEXED = 0x1 28 FI_STORE_TERMVECTOR = 0x2 29 FI_STORE_OFFSETS_IN_POSTINGS = 0x4 30 FI_OMIT_NORMS = 0x10 31 FI_STORE_PAYLOADS = 0x20 32 FI_OMIT_TERM_FREQ_AND_POSITIONS = 0x40 33 FI_OMIT_POSITIONS = 0x80 34 ) 35 36 type Lucene46FieldInfosFormat struct { 37 r FieldInfosReader 38 w FieldInfosWriter 39 } 40 41 func NewLucene46FieldInfosFormat() *Lucene46FieldInfosFormat { 42 return &Lucene46FieldInfosFormat{ 43 r: Lucene46FieldInfosReader, 44 w: Lucene46FieldInfosWriter, 45 } 46 } 47 48 func (f *Lucene46FieldInfosFormat) FieldInfosReader() FieldInfosReader { 49 return f.r 50 } 51 52 func (f *Lucene46FieldInfosFormat) FieldInfosWriter() FieldInfosWriter { 53 return f.w 54 } 55 56 var Lucene46FieldInfosReader = func(dir store.Directory, 57 segment, suffix string, ctx store.IOContext) (fis FieldInfos, err error) { 58 59 filename := util.SegmentFileName(segment, suffix, FI_EXTENSION) 60 var input store.ChecksumIndexInput 61 if input, err = dir.OpenChecksumInput(filename, ctx); err != nil { 62 return 63 } 64 65 var success = false 66 defer func() { 67 if success { 68 err = input.Close() 69 } else { 70 util.CloseWhileSuppressingError(input) 71 } 72 }() 73 74 var codecVersion int 75 if codecVersion, err = asInt(codec.CheckHeader(input, FI_CODEC_NAME, FI_FORMAT_START, FI_FORMAT_CURRENT)); err != nil { 76 return 77 } 78 79 var size int 80 if size, err = asInt(input.ReadVInt()); err != nil { 81 return 82 } 83 84 var infos []*FieldInfo 85 var name string 86 var fieldNumber int32 87 var bits, val byte 88 var isIndexed, storeTermVector, omitNorms, storePayloads bool 89 var indexOptions IndexOptions 90 var docValuesType, normsType DocValuesType 91 var dvGen int64 92 var attributes map[string]string 93 for i := 0; i < size; i++ { 94 if name, err = input.ReadString(); err != nil { 95 return 96 } 97 if fieldNumber, err = input.ReadVInt(); err != nil { 98 return 99 } 100 assert2(fieldNumber >= 0, 101 "invalid field number for field: %v, fieldNumber=%v (resource=%v)", 102 name, fieldNumber, input) 103 if bits, err = input.ReadByte(); err != nil { 104 return 105 } 106 isIndexed = (bits & FI_IS_INDEXED) != 0 107 storeTermVector = (bits & FI_STORE_TERMVECTOR) != 0 108 omitNorms = (bits & FI_OMIT_NORMS) != 0 109 storePayloads = (bits & FI_STORE_PAYLOADS) != 0 110 switch { 111 case !isIndexed: 112 // 113 case (bits & FI_OMIT_TERM_FREQ_AND_POSITIONS) != 0: 114 indexOptions = INDEX_OPT_DOCS_ONLY 115 case (bits & FI_OMIT_POSITIONS) != 0: 116 indexOptions = INDEX_OPT_DOCS_AND_FREQS 117 case (bits & FI_STORE_OFFSETS_IN_POSTINGS) != 0: 118 indexOptions = INDEX_OPT_DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS 119 default: 120 indexOptions = INDEX_OPT_DOCS_AND_FREQS_AND_POSITIONS 121 } 122 123 // DV types are packed in one byte 124 if val, err = input.ReadByte(); err != nil { 125 return 126 } 127 if docValuesType, err = getDocValuesType(input, val&0x0F); err != nil { 128 return 129 } 130 if normsType, err = getDocValuesType(input, (val>>4)&0x0F); err != nil { 131 return 132 } 133 if dvGen, err = input.ReadLong(); err != nil { 134 return 135 } 136 if attributes, err = input.ReadStringStringMap(); err != nil { 137 return 138 } 139 infos = append(infos, NewFieldInfo(name, isIndexed, fieldNumber, 140 storeTermVector, omitNorms, storePayloads, indexOptions, 141 docValuesType, normsType, dvGen, attributes)) 142 } 143 144 if codecVersion >= FI_FORMAT_CHECKSUM { 145 if _, err = codec.CheckFooter(input); err != nil { 146 return 147 } 148 } else { 149 if err = codec.CheckEOF(input); err != nil { 150 return 151 } 152 } 153 fis = NewFieldInfos(infos) 154 success = true 155 return fis, nil 156 } 157 158 func getDocValuesType(input store.IndexInput, b byte) (t DocValuesType, err error) { 159 switch b { 160 case 0: 161 return DocValuesType(0), nil 162 case 1: 163 return DOC_VALUES_TYPE_NUMERIC, nil 164 case 2: 165 return DOC_VALUES_TYPE_BINARY, nil 166 case 3: 167 return DOC_VALUES_TYPE_SORTED, nil 168 case 4: 169 return DOC_VALUES_TYPE_SORTED_SET, nil 170 default: 171 return DocValuesType(0), errors.New( 172 fmt.Sprintf("invalid docvalues byte: %v (resource=%v)", b, input)) 173 } 174 } 175 176 var Lucene46FieldInfosWriter = func(dir store.Directory, 177 segName, suffix string, infos FieldInfos, ctx store.IOContext) (err error) { 178 179 filename := util.SegmentFileName(segName, suffix, FI_EXTENSION) 180 var output store.IndexOutput 181 if output, err = dir.CreateOutput(filename, ctx); err != nil { 182 return 183 } 184 185 var success = false 186 defer func() { 187 if success { 188 err = output.Close() 189 } else { 190 util.CloseWhileSuppressingError(output) 191 } 192 }() 193 194 if err = codec.WriteHeader(output, FI_CODEC_NAME, FI_FORMAT_CURRENT); err != nil { 195 return 196 } 197 if err = output.WriteVInt(int32(infos.Size())); err != nil { 198 return 199 } 200 for _, fi := range infos.Values { 201 indexOptions := fi.IndexOptions() 202 bits := byte(0) 203 if fi.HasVectors() { 204 bits |= FI_STORE_TERMVECTOR 205 } 206 if fi.OmitsNorms() { 207 bits |= FI_OMIT_NORMS 208 } 209 if fi.HasPayloads() { 210 bits |= FI_STORE_PAYLOADS 211 } 212 if fi.IsIndexed() { 213 bits |= FI_IS_INDEXED 214 assert(indexOptions >= INDEX_OPT_DOCS_AND_FREQS_AND_POSITIONS || !fi.HasPayloads()) 215 switch indexOptions { 216 case INDEX_OPT_DOCS_ONLY: 217 bits |= FI_OMIT_TERM_FREQ_AND_POSITIONS 218 case INDEX_OPT_DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS: 219 bits |= FI_STORE_OFFSETS_IN_POSTINGS 220 case INDEX_OPT_DOCS_AND_FREQS: 221 bits |= FI_OMIT_POSITIONS 222 } 223 } 224 if err = output.WriteString(fi.Name); err == nil { 225 if err = output.WriteVInt(fi.Number); err == nil { 226 err = output.WriteByte(bits) 227 } 228 } 229 if err != nil { 230 return 231 } 232 233 // pack the DV types in one byte 234 dv := byte(fi.DocValuesType()) 235 nrm := byte(fi.NormType()) 236 assert((dv&(^byte(0xF))) == 0 && (nrm&(^byte(0x0F))) == 0) 237 val := (0xff & ((nrm << 4) | dv)) 238 if err = output.WriteByte(val); err == nil { 239 if err = output.WriteLong(fi.DocValuesGen()); err == nil { 240 err = output.WriteStringStringMap(fi.Attributes()) 241 } 242 } 243 if err != nil { 244 return 245 } 246 } 247 if err = codec.WriteFooter(output); err != nil { 248 return 249 } 250 success = true 251 return nil 252 } 253 254 func assert(ok bool) { 255 if !ok { 256 panic("assert fail") 257 } 258 } 259 260 func assert2(ok bool, msg string, args ...interface{}) { 261 if !ok { 262 panic(fmt.Sprintf(msg, args...)) 263 } 264 }