package org.apache.solr.request.join; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import org.apache.lucene.index.SegmentReader; import org.apache.lucene.util.cache.Cache; import org.apache.solr.request.uninverted.GrobalCache; import org.apache.solr.request.uninverted.GrobalCache.ILruMemSizeCache; import org.apache.solr.request.uninverted.GrobalCache.ILruMemSizeKey; import org.apache.solr.schema.FieldType; import org.apache.solr.schema.IndexSchema; import org.apache.solr.search.SolrIndexSearcher; import com.alimama.mdrill.buffer.LuceneUtils; public class HigoJoin { public static Object lock=new Object(); public static HigoJoinInterface getJoin(SegmentReader reader,String partion,IndexSchema schema, SolrIndexSearcher readerright, String fieldLeft, String fieldRigth) throws IOException { Cache<ILruMemSizeKey, ILruMemSizeCache> cache = GrobalCache.fieldValueCache; StringBuffer key = new StringBuffer(); key.append("sig@"); key.append(partion); key.append("@"); key.append(fieldLeft); key.append("@"); key.append(LuceneUtils.crcKey(reader)); key.append("@"); key.append(readerright.getPartionKey()); key.append("@"); key.append(fieldRigth); key.append("@"); key.append(LuceneUtils.crcKey(readerright.getReader())); String cachekey = key.toString(); GrobalCache.StringKey fvkey = new GrobalCache.StringKey(cachekey); HigoJoinInterface uif = (HigoJoinInterface) cache.get(fvkey); if (uif == null) { synchronized (lock) { uif = (HigoJoinInterface) cache.get(fvkey); if (uif == null) { FieldType ftleft=schema.getFieldType(fieldLeft); FieldType ftright =readerright.getSchema().getFieldType(fieldRigth); if(ftleft.isMultiValued()||ftright.isMultiValued()) { throw new IOException("multi value"); }else{ uif = new HigoJoinSingleValues(reader,partion,schema,readerright,fieldLeft, fieldRigth); } cache.put(fvkey, uif); } } } return uif; } private static int INT_SIZE = Integer.SIZE / 8; public static class IntArr { public int[] list = new int[0]; public static IntArr parse(Integer d) { IntArr rtn = new IntArr(); rtn.list = new int[1]; rtn.list[0]=d; return rtn; } public static IntArr parse(ArrayList<Integer> d) { IntArr rtn = new IntArr(); rtn.list = new int[d.size()]; int index = 0; for (Integer v : d) { rtn.list[index] = v; index++; } return rtn; } public static IntArr parse(HashSet<Integer> d) { IntArr rtn = new IntArr(); rtn.list = new int[d.size()]; int index = 0; for (Integer v : d) { rtn.list[index] = v; index++; } return rtn; } public long memsize() { return 8 + 8 + list.length * INT_SIZE; } } public static class JoinPariArr { public JoinPair[] list = new JoinPair[0]; public long memsize() { long memsize = 8 + 8; for (JoinPair p : this.list) { memsize += p.memsize(); } return memsize; } public static JoinPariArr parse(ArrayList<JoinPair> d) { JoinPariArr rtn = new JoinPariArr(); rtn.list = new JoinPair[d.size()]; int index = 0; for (JoinPair v : d) { rtn.list[index] = v; index++; } return rtn; } } static class JoinPair { int termNum; int[] left; public long memsize() { return (left.length + 2) * INT_SIZE + 16; } @Override public String toString() { return "JoinPair [termNum=" + termNum + ", left=" + Arrays.toString(left) + "]"; } } static class JoinTermNum { public JoinTermNum(Integer docId, Integer termNum) { super(); this.leftId = docId; this.termNum = termNum; } int leftId = -1; int termNum = -1; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + leftId; result = prime * result + termNum; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; JoinTermNum other = (JoinTermNum) obj; if (leftId != other.leftId) return false; if (termNum != other.termNum) return false; return true; } public long memsize() { return 8 + INT_SIZE * 2; } } }