package org.apache.solr.request.uninverted; import java.io.IOException; import java.util.Comparator; import java.util.concurrent.ExecutorCompletionService; import org.apache.lucene.index.Term; import org.apache.lucene.index.TermDocs; import org.apache.lucene.util.cache.Cache; import org.apache.lucene.util.cache.SimpleLRUCache; import org.apache.solr.request.BlockBufferPool.BlockArray; import org.apache.solr.request.uninverted.GrobalCache.ILruMemSizeKey; import org.apache.solr.schema.DoubleField; import org.apache.solr.schema.FieldType; import org.apache.solr.schema.LongField; import org.apache.solr.schema.StrField; import org.apache.solr.schema.TrieDoubleField; import org.apache.solr.schema.TrieLongField; public class UnInvertedFieldUtils { public static enum FieldDatatype{ d_default, d_string, d_long, d_double } public static enum CompressType{ d_byte, d_short, d_int, } public static Comparator<MixTermInfo> TD_CMP=new Comparator<MixTermInfo>() { @Override public int compare(MixTermInfo o1, MixTermInfo o2) { int t1=o1.getCount()/1024; int t2=o2.getCount()/1024; if(t1 == t2) { int tt1=o1.getTermNum(); int tt2=o2.getTermNum(); return tt1 == tt2 ? 0 : tt1 > tt2 ? 1 : -1; } return t1 < t2 ? 1 : -1; } }; public static Comparator<MixTermInfo> TD_CMP_TM=new Comparator<MixTermInfo>() { @Override public int compare(MixTermInfo o1, MixTermInfo o2) { int tt1=o1.getTermNum(); int tt2=o2.getTermNum(); return tt1 == tt2 ? 0 : tt1 > tt2 ? 1 : -1; } }; public static interface Doc2TmInterface{ public Integer get(int i); public void set(int i,Number v); public Integer getsize(); } public static class IntDoc2Tm implements Doc2TmInterface{ BlockArray<Integer> arr; public IntDoc2Tm(BlockArray<Integer> arr) { this.arr = arr; } public Integer get(int i){ return this.arr.get(i); } public Integer getsize() { return this.arr.getSize(); } @Override public void set(int i, Number v) { this.arr.set(i, v.intValue()); } } public static class ByteDoc2Tm implements Doc2TmInterface{ BlockArray<Byte> arr; public ByteDoc2Tm(BlockArray<Byte> arr) { this.arr = arr; } public Integer get(int i){ return (int)this.arr.get(i); } public Integer getsize() { return this.arr.getSize(); } @Override public void set(int i, Number v) { this.arr.set(i, v.byteValue()); } } public static class ShortDoc2Tm implements Doc2TmInterface{ BlockArray<Short> arr; public ShortDoc2Tm(BlockArray<Short> arr) { this.arr = arr; } public Integer get(int i){ return (int)this.arr.get(i); } public Integer getsize() { return this.arr.getSize(); } @Override public void set(int i, Number v) { this.arr.set(i, v.shortValue()); } } public static int compressTypeToInt(CompressType dt) { if(dt==CompressType.d_byte) { return 1; } if(dt==CompressType.d_short) { return 2; } return 0; } public static CompressType intToCompressType(int d) { switch (d) { case 1: { return CompressType.d_byte; } case 2: { return CompressType.d_short; } default: { return CompressType.d_int; } } } public static int fieldDataTypeToInt(FieldDatatype dt) { if(dt==FieldDatatype.d_string) { return 1; } if(dt==FieldDatatype.d_long) { return 2; } if(dt==FieldDatatype.d_double) { return 3; } return 0; } public static FieldDatatype intToFieldDataType(int d) { switch (d) { case 1: { return FieldDatatype.d_string; } case 2: { return FieldDatatype.d_long; } case 3: { return FieldDatatype.d_double; } default: { return FieldDatatype.d_default; } } } public static FieldDatatype getDataType(FieldType ft) { FieldDatatype dataType=FieldDatatype.d_default; if(ft instanceof StrField) { dataType=FieldDatatype.d_string; }else if(ft instanceof LongField||ft instanceof TrieLongField) { dataType=FieldDatatype.d_long; }else if(ft instanceof DoubleField||ft instanceof TrieDoubleField) { dataType=FieldDatatype.d_double; }else{ dataType=FieldDatatype.d_default; } return dataType; } /** Number of bytes to represent an unsigned int as a vint. */ public static int vIntSize(int x) { if ((x & (0xffffffff << (7*1))) == 0 ) { return 1; } if ((x & (0xffffffff << (7*2))) == 0 ) { return 2; } if ((x & (0xffffffff << (7*3))) == 0 ) { return 3; } if ((x & (0xffffffff << (7*4))) == 0 ) { return 4; } return 5; } // todo: if we know the size of the vInt already, we could do // a single switch on the size public static int writeInt(int x, byte[] arr, int pos) { int a; a = (x >>> (7*4)); if (a != 0) { arr[pos++] = (byte)(a | 0x80); } a = (x >>> (7*3)); if (a != 0) { arr[pos++] = (byte)(a | 0x80); } a = (x >>> (7*2)); if (a != 0) { arr[pos++] = (byte)(a | 0x80); } a = (x >>> (7*1)); if (a != 0) { arr[pos++] = (byte)(a | 0x80); } arr[pos++] = (byte)(x & 0x7f); return pos; } public static class UnivertPool{ public UnInvertedField uni; public IOException e=null; } private static Cache<ILruMemSizeKey, Object> LOCK = Cache.synchronizedCache(new SimpleLRUCache<ILruMemSizeKey, Object>(1024)); public static synchronized Object getLock(final ILruMemSizeKey key) { Object lockobj=LOCK.get(key); if(lockobj==null) { lockobj=new Object(); LOCK.put(key, lockobj); } return lockobj; } public static UnInvertedField takeUnf(ExecutorCompletionService<UnivertPool> serv) throws IOException { UnInvertedField uif=null; try { UnivertPool rtnuif = serv.take().get(); if(rtnuif.e!=null) { throw rtnuif.e; } uif=rtnuif.uni; } catch (Throwable e) { throw new IOException(e); } return uif; } public static final int NO_MORE_DOCS = Integer.MAX_VALUE; public static int advance(TermDocs termDocs, int target) throws IOException { try { int doc = NO_MORE_DOCS; boolean result = termDocs.skipTo(target); if (result) { doc = termDocs.doc(); } return doc; } catch (Throwable e) { UnInvertedField.log.error("advance " + target, e); return NO_MORE_DOCS; } } public static class MixTermInfo { private int count = 0; private Term tm = null; private int termNum = 0; private TermDocs td; public MixTermInfo(int count, int termNum, TermDocs td, Term tm) { this.count = count; this.termNum = termNum; this.td = td; this.tm = tm; } public int getTermNum() { return termNum; } public int getCount() { return count; } public TermDocs getTd() throws IOException { this.td.seek(tm); return this.td; } } }