content: 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;
  	}
  
  }
  