package org.apache.solr.request.uninverted;
import java.io.IOException;
import java.util.HashSet;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.util.cache.Cache;
import org.apache.lucene.util.cache.SimpleLRUCache;
import org.apache.solr.request.BlockBufferPool;
import org.apache.solr.request.BlockBufferPool.BlockArray;
import org.apache.solr.request.uninverted.RamTermNumValue.TermDoubleValue;
import org.apache.solr.request.uninverted.UnInvertedFieldUtils.Doc2TmInterface;
import org.apache.solr.request.uninverted.UnInvertedFieldUtils.ByteDoc2Tm;
import org.apache.solr.request.uninverted.UnInvertedFieldUtils.IntDoc2Tm;
import org.apache.solr.request.uninverted.UnInvertedFieldUtils.ShortDoc2Tm;
import org.apache.solr.request.uninverted.UnInvertedFieldUtils.CompressType;
import org.apache.solr.schema.FieldType;
import com.alimama.mdrill.utils.UniqConfig;
public class RamDocValue {
// public static Logger log = LoggerFactory.getLogger(RamDocValue.class);
public RamTermNumValue tmValue=null;
public UnInvertedFieldUtils.CompressType indexDatatype = UnInvertedFieldUtils.CompressType.d_int;
public BlockArray<Integer> index = null;
public BlockArray<Short> indexshort = null;
public BlockArray<Byte> indexbyte = null;
public RamDocValue(UnInvertedFieldUtils.FieldDatatype fieldDataType)
{
this.tmValue=new RamTermNumValue(fieldDataType);
}
public DocReaderNull getDocReaderNull()
{
DocReaderNull rnt= new DocReaderNull();
rnt.setUni(this);
return rnt;
}
public DocReaderSingle getDocReader()
{
DocReaderSingle rnt= new DocReaderSingle();
rnt.setUni(this);
return rnt;
}
public void startInitValue(int maxDoc, IndexReader reader,boolean isReadDouble) {
int maxDocOffset = maxDoc + 2;
this.index = BlockBufferPool.INT_POOL.calloc(maxDocOffset,BlockBufferPool.INT_CREATE, -1);
this.tmValue.startInitValue(maxDoc, reader, isReadDouble);
}
public void endInitValue(boolean isReadDouble, int maxTermNum) {
this.tmValue.endInitValue(isReadDouble, maxTermNum);
this.compressDoc2Tm();
}
private void compressDoc2Tm() {
int nullTerm=this.tmValue.nullTermNum;
int checkValue=nullTerm+1;
int size = this.index.getSize();
if (checkValue< Byte.MAX_VALUE) {
this.indexDatatype = UnInvertedFieldUtils.CompressType.d_byte;
this.indexbyte = BlockBufferPool.BYTE_POOL.calloc(size,BlockBufferPool.BYTE_CREATE, (byte) nullTerm);
this.indexbyte.fillByInt(this.index, -1);
BlockBufferPool.INT_POOL.recycleByteBlocks(this.index);
this.index = null;
} else if (checkValue < Short.MAX_VALUE) {
this.indexDatatype = UnInvertedFieldUtils.CompressType.d_short;
this.indexshort = BlockBufferPool.SHORT_POOL.calloc(size,BlockBufferPool.SHORT_CREATE, (short) nullTerm);
this.indexshort.fillByInt(this.index, -1);
BlockBufferPool.INT_POOL.recycleByteBlocks(this.index);
this.index = null;
} else {
this.indexDatatype = UnInvertedFieldUtils.CompressType.d_int;
this.index.replace(-1, nullTerm);
}
}
public void free() {
if (this.index != null) {
BlockBufferPool.INT_POOL.recycleByteBlocks(this.index);
this.index=null;
}
if (this.indexshort != null) {
BlockBufferPool.SHORT_POOL.recycleByteBlocks(this.indexshort);
this.indexshort=null;
}
if (this.indexbyte != null) {
BlockBufferPool.BYTE_POOL.recycleByteBlocks(this.indexbyte);
this.indexbyte=null;
}
this.tmValue.free();
}
public Doc2TmInterface getDocTmReader() {
if (this.indexDatatype.equals(CompressType.d_byte)) {
return new ByteDoc2Tm(this.indexbyte);
}
if (this.indexDatatype.equals(CompressType.d_short)) {
return new ShortDoc2Tm(this.indexshort);
}
return new IntDoc2Tm(this.index);
}
private TermDoubleValue getTermDoubleValue()
{
return this.tmValue.getTermDoubleValue();
}
public static class DocReaderSingle implements
DocValueReadInterface {
private RamDocValue uni;
private TermDoubleValue termNumberValue;
private Doc2TmInterface doc2tm = null;
public void setUni(RamDocValue uni) {
this.uni = uni;
this.termNumberValue = uni.getTermDoubleValue();
this.doc2tm = uni.getDocTmReader();
}
@Override
public double quickToDouble(int doc, FieldType ft, TermNumEnumerator te)
throws IOException {
int tnum = this.doc2tm.get(doc);
if (tnum >= this.uni.tmValue.nullTermNum) {
return RamTermNumValue.TERMNUM_NAN_VALUE;
}
return this.termNumberValue.tm(tnum, ft, te);
}
public Integer termNum(int doc, Integer def) throws IOException {
int tnum = this.doc2tm.get(doc);
if (tnum >= this.uni.tmValue.nullTermNum) {
return def;
}
return tnum;
}
private Cache<Integer, String> termsCache = Cache.synchronizedCache(new SimpleLRUCache<Integer, String>(UniqConfig.getTermCacheSize()));
private String getTermText(TermNumEnumerator te, int termNum)
throws IOException {
String termText = termsCache.get(termNum);
if (termText != null) {
return termText;
}
if (!te.skipTo(termNum)) {
return null;
}
Term t = te.term();
if (t == null) {
return null;
}
termText = t.text();
if (termText == null) {
return null;
}
termsCache.put(termNum, termText);
return termText;
}
public String tNumToString(int tnum, FieldType ft,
TermNumEnumerator te, String def) throws IOException {
if (tnum >= this.uni.tmValue.nullTermNum) {
return def;
}
String termText = this.getTermText(te, tnum);
if (termText != null) {
return ft.indexedToReadable(termText);
}
return def;
}
@Override
public void setTermNum(int doc, int tm) throws IOException {
this.doc2tm.set(doc, tm);
}
}
public static interface DocValueReadInterface {
public void setUni(RamDocValue uni);
public double quickToDouble(int doc, FieldType ft, TermNumEnumerator te)
throws IOException;
public Integer termNum(int doc, Integer def) throws IOException;
public void setTermNum(int doc, int tm) throws IOException;
public String tNumToString(int tnum, FieldType ft,
TermNumEnumerator te, String def) throws IOException;
}
public static class DocReaderNull implements DocValueReadInterface {
HashSet<Integer> rtn = new HashSet<Integer>();
public void setUni(RamDocValue uni) {
}
@Override
public double quickToDouble(int doc, FieldType ft, TermNumEnumerator te)
throws IOException {
return RamTermNumValue.TERMNUM_NAN_VALUE;
}
public Integer termNum(int doc, Integer def) throws IOException {
return def;
}
@Override
public String tNumToString(int tnum, FieldType ft,
TermNumEnumerator te, String def) throws IOException {
return def;
}
@Override
public void setTermNum(int doc, int tm) throws IOException {
}
}
public int getmemsize() {
int sz = 0;
if (index != null)
sz += index.getMemSize() * 4;
if (indexshort != null)
sz += indexshort.getMemSize() * 2;
if (indexbyte != null)
sz += indexbyte.getMemSize() * 1;
sz += this.tmValue.getmemsize();
return sz;
}
public String toString() {
StringBuffer membuffer = new StringBuffer();
if (index != null) {
membuffer.append(",").append(
"index=" + index.getMemSize() + "@" + index.getSize());
}
if (indexshort != null) {
membuffer.append(",").append(
"indexshort=" + indexshort.getMemSize() + "@"
+ indexshort.getSize());
}
if (indexbyte != null) {
membuffer.append(",").append(
"indexbyte=" + indexbyte.getMemSize() + "@"
+ indexbyte.getSize());
}
membuffer.append(",").append(this.tmValue.toString());
return membuffer.toString();
}
}