package org.apache.solr.request.uninverted;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.SegmentReader;
import org.apache.lucene.util.OpenBitSet;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.handler.component.StatsValues;
import org.apache.solr.request.BlockBufferPool.BlockArray;
import org.apache.solr.request.uninverted.RamDocValue.DocValueReadInterface;
import org.apache.solr.request.uninverted.UnInvertedFieldUtils.FieldDatatype;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.TrieField;
import org.apache.solr.search.BitDocSet;
import org.apache.solr.search.DocSet;
import org.apache.solr.search.SolrIndexSearcher;
public class UnInvertedFieldBase implements GrobalCache.ILruMemSizeCache {
// public static Logger log = LoggerFactory.getLogger(UnInvertedFieldBase.class);
public AtomicInteger refCnt = new AtomicInteger(0);
public UnInvertedFieldUtils.FieldDatatype fieldDataType = UnInvertedFieldUtils.FieldDatatype.d_default;
public String field;
public FieldType ft;
public TermIndex ti;
public RamDocValue ramDocValue =null;
//mark history
public BitDocSet bits;
//read current
public BitDocSet baseAdvanceDocs = null;
private boolean isShutDown = false;
public boolean isShutDown() {
return isShutDown;
}
public boolean isMultiValued = false;
public boolean isNullField = false;
public DocValueReadInterface tnr;
public void init(String field, IndexReader reader,IndexSchema schema) throws IOException
{
this.bits = new BitDocSet(new OpenBitSet(reader.maxDoc()));
this.field = field;
FieldType schemaft=schema.getFieldType(field);
String prefix=TrieField.getMainValuePrefix(schemaft);
SchemaField sf = schema.getField(field);
this.ft = sf.getType();
this.isMultiValued = this.ft.isMultiValued();
this.fieldDataType = UnInvertedFieldUtils.getDataType(this.ft);
this.ramDocValue=new RamDocValue(this.fieldDataType);
this.ti = new TermIndex(field, prefix);
}
public void setTmValueDouble(int tm, double val) {
// log.info("setTmValueDouble "+tm+","+val);
this.ramDocValue.tmValue.termValueDouble.set(tm, val);
}
public void setTmValueLong(int tm, long val) {
// log.info("setTmValueLong "+tm+","+val);
this.ramDocValue.tmValue.termValueLong.set(tm, val);
}
public BlockArray<Double> getTmValueDouble() {
return this.ramDocValue.tmValue.termValueDouble;
}
public BlockArray<Long> getTmValueLong() {
return this.ramDocValue.tmValue.termValueLong;
}
public void markDocTm(int doc, int termNum, boolean isinit)
throws IOException {
if (isinit) {
this.ramDocValue.index.set(doc, termNum);
} else {
this.tnr.setTermNum(doc, termNum);
}
}
public void startRamDocValue(int maxDoc, IndexReader reader,
boolean isReadDouble) {
ramDocValue.startInitValue(maxDoc, reader, isReadDouble);
}
public void endRamDocValue(boolean isReadDouble, int maxTermNum) {
this.ramDocValue.endInitValue(isReadDouble, maxTermNum);
}
public boolean checkEmpty() throws IOException {
if (this.field.indexOf("higoempty_") >= 0) {
this.isNullField = true;
}
if (this.isNullField) {
this.tnr = this.ramDocValue.getDocReaderNull();
return true;
}
if(this.isMultiValued)
{
throw new IOException("unsupport MultiValued");
}
return false;
}
public TermNumEnumerator getTi(SolrIndexSearcher searcher)
throws IOException {
return ti.getEnumerator(searcher.getReader());
}
public TermNumEnumerator getTi(SegmentReader reader) throws IOException {
return ti.getEnumerator(reader);
}
public int getNullTm() {
return this.ramDocValue.tmValue.nullTermNum;
}
public Integer termNum(int doc) throws IOException {
return this.tnr.termNum(doc, this.getNullTm());
}
// group by
public String tNumToString(int tnum, FieldType ft, TermNumEnumerator te,
String def) throws IOException {
String rtn= this.tnr.tNumToString(tnum, ft, te, def);
return rtn;
}
// sum,dist
public double quickToDouble(int doc, FieldType ft, TermNumEnumerator te)
throws IOException {
try{
return this.tnr.quickToDouble(doc, ft, te);
}catch(Throwable e)
{
return RamTermNumValue.TERMNUM_NAN_VALUE;
}
}
public int getTermNum(TermNumEnumerator te, String text, FieldType ft)
throws IOException {
//TODO ----这个地方显得多余,之后考虑注释掉 在试试 ----
if ((text.startsWith("_") || text.startsWith("null"))&& !this.fieldDataType.equals(FieldDatatype.d_string)) {
return this.getNullTm();
}
if (te.skipTo(ft.toInternal(text))) {
return te.getTermNumber();
} else {
return this.getNullTm();
}
}
@Override
public String toString() {
return "{field=" + field + ",memSize=" + (memSize() * 1.0 / 1024 / 1024) + "mb" + ",nullTermNum=" + this.getNullTm() + this.ramDocValue.toString() +",bits.size="+this.bits.size()+ "}";
}
private void freeMem() {
if (isShutDown) {
return;
}
isShutDown = true;
this.ramDocValue.free();
}
public void LRUclean() {
if (this.refCnt.get() == 0) {
this.freeMem();
}
}
protected void finalize() throws Throwable {
super.finalize();
this.freeMem();
}
long sz = -1;
public synchronized long memSize() {
if (sz > 0) {
return sz;
}
sz = 8 * 8 + 32; // local fields
if (bits != null)
sz += bits.memSize();
if (baseAdvanceDocs != null)
sz += baseAdvanceDocs.memSize();
sz += ramDocValue.getmemsize();
sz += ti.memSize();
return sz;
}
/**
* 旧的solr接口,已经废弃
*/
public NamedList getCounts(SolrIndexSearcher searcher, DocSet baseDocs,
int offset, int limit, Integer mincount, boolean missing,
String sort, String prefix, Boolean returnPair, boolean isRow)
throws IOException {
return new NamedList();
}
/**
* 旧的solr接口,已经废弃
*/
public StatsValues getStats(SolrIndexSearcher searcher, DocSet baseDocs,
String[] facet) throws IOException {
return null;
}
}