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  }