content: package org.apache.solr.request.mdrill;
  
  import java.io.IOException;
  import java.net.UnknownHostException;
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.PriorityQueue;
  import java.util.concurrent.ConcurrentHashMap;
  import java.util.zip.CRC32;
  
  import org.apache.lucene.document.Document;
  import org.apache.lucene.document.Fieldable;
  import org.apache.lucene.document.MapFieldSelector;
  import org.apache.lucene.index.SegmentReader;
  import org.apache.lucene.queryParser.ParseException;
  import org.apache.solr.common.params.SolrParams;
  import org.apache.solr.common.util.NamedList;
  import org.apache.solr.schema.FieldType;
  import org.apache.solr.schema.IndexSchema;
  import org.apache.solr.search.DocIterator;
  import org.apache.solr.search.DocSet;
  import org.apache.solr.search.SolrIndexSearcher;
  
  import org.apache.solr.request.SolrQueryRequest;
  import org.apache.solr.request.compare.ColumnKey;
  import org.apache.solr.request.compare.RecordCountDetail;
  import org.apache.solr.request.compare.SelectDetailRow;
  import org.apache.solr.request.compare.ShardDetailSelectDetailRowStringCompare;
  
  import com.alimama.mdrill.utils.EncodeUtils;
  import com.alimama.mdrill.utils.UniqConfig;
  
  /**
  	查询明细的实现-无排序，无join
   * @author yannian.mu
   */
  public class MdrillDetailFdt {
  	private SolrIndexSearcher searcher;
  	private RecordCountDetail recordCount ;
  	private SolrQueryRequest req;
  	private MdrillParseDetailFdt parse;
  	private SegmentReader reader;
  	private MdrillParseDetailFdt.fetchContaioner container=null;
  	String crcget=null;
  	String segKey=null;
  	private String hostId=java.util.UUID.randomUUID().toString();
  	SolrParams params;
  	public MdrillDetailFdt(SolrIndexSearcher _searcher,SegmentReader reader,SolrParams _params,SolrQueryRequest req)
  	{
  		try {
  			this.hostId=java.net.InetAddress.getLocalHost().getHostAddress()+","+String.valueOf(java.net.InetAddress.getLocalHost().getHostName());
  		} catch (UnknownHostException e) {
  			hostId=java.util.UUID.randomUUID().toString();
  		}
  		this.segKey=reader.getSigmentUniqKey();
  		this.reader=reader;
  		this.req=req;
  		this.searcher=_searcher;
  		this.parse=new MdrillParseDetailFdt(_params);
  		this.crcget=_params.get("mdrill.crc.key.get",null);
  		this.recordCount = new RecordCountDetail();
  		this.params=_params;
  	}
  	
  	public static class Doclist{
  		public int[] list;
  		public Doclist(int size) {
  			super();
  			this.list = new int[size];
  		}
  		
  		public void add(int doc)
  		{
  			list[index]=doc;
  			this.index++;
  		}
  		public int index=0;
  	}
  
  	public NamedList get(String[] fields, DocSet baseDocs) throws IOException,
  			ParseException {
  			if(this.crcget==null)
  			{
  				this.container=this.parse.createContainer(fields, baseDocs, this.reader, this.searcher, this.req);
  				DocIterator iter = baseDocs.iterator();
  				this.recordCount.inc(baseDocs.size());
  				Doclist res=new Doclist(this.parse.limit_offset);
  				int doc=-1;
  				while (iter.hasNext()) {
  					doc = iter.nextDoc();
  					res.add(doc);
  					if(res.index>=this.parse.limit_offset)
  					{
  						break;
  					}
  				}
  				PriorityQueue<SelectDetailRow> topItems=this.transGroupValue(res,fields);
  				this.container.free();
  				return this.toNameList(topItems);	
  		}
  			String hostkey=String.valueOf(this.getkeyCrc());
  
  			ConcurrentHashMap<Long,String> cache=MdrillUtils.CRC_CACHE_SIZE.remove(crcget+"@"+hostkey);
  
  			
  			NamedList rtn=new NamedList();
  			Map<Long,String> crcvalue=new HashMap<Long,String>();
  			rtn.add("fdtcre", crcvalue);
  			if(cache!=null)
  			{
  				MapFieldSelector selector=new MapFieldSelector(fields); 
  				FieldType[] ftlist=new FieldType[fields.length];
  				IndexSchema schema=this.searcher.getSchema();
  
  				for (int j = 0; j < fields.length; j++) {
  					ftlist[j]=schema.getFieldType(fields[j]);
  					
  				}
  
  				String crcliststr=params.get("mdrill.crc.key.get.crclist");
  				if(crcliststr!=null)
  				{
  					String[] crclist=crcliststr.split(",");
  					for(String s:crclist)
  					{
  						Long crc=Long.parseLong(s);
  						String v=cache.get(crc);
  						if(v!=null)
  						{
  							String cols[]=v.split(UniqConfig.GroupJoinString(),-1);
  							if(cols.length>=2)
  							{
  								int doc=Integer.parseInt(cols[0]);
  								
  								SortGroupVal buff = new SortGroupVal();
  								buff.groupbuff.append("-");
  								buff.groupbuff.append(UniqConfig.GroupJoinString());
  								buff.groupbuff.append("-");
  								Document docfields=this.reader.document(doc,selector);
  								if(docfields==null)
  								{
  									for (int j = 0; j < fields.length; j++) {
  										buff.groupbuff.append(UniqConfig.GroupJoinString());
  										buff.groupbuff.append(EncodeUtils.encode("-"));
  									}
  									if(!crcvalue.containsKey(crc))
  									{
  										crcvalue.put(crc, buff.groupbuff.toString());
  									}
  								}else{
  
  									for (int j = 0; j < fields.length; j++) {
  										buff.groupbuff.append(UniqConfig.GroupJoinString());
  	
  										Fieldable fv=docfields.getFieldable(fields[j]);
  										
  										
  										if(fv!=null)
  										{
  											buff.groupbuff.append(EncodeUtils.encode(ftlist[j].toExternal(fv)));
  										}
  										else{
  											buff.groupbuff.append(EncodeUtils.encode("-"));
  										}
  									}
  									crcvalue.put(crc, buff.groupbuff.toString());
  
  								}
  							}
  						}
  					}
  				}
  			}
  			return rtn;
  	}
  	
  
  	private long getkeyCrc()
  	{
  		CRC32 crc32 = new CRC32();
  		crc32.update(String.valueOf(hostId+"@"+this.segKey).getBytes());
  		return crc32.getValue();
  	}
  	
  
  
  public PriorityQueue<SelectDetailRow> transGroupValue(Doclist res,String[] fields)throws ParseException, IOException {
  		
  		long key=getkeyCrc();
  
  		PriorityQueue<SelectDetailRow> topItems = new PriorityQueue<SelectDetailRow>(this.parse.limit_offset, Collections.reverseOrder(defcmp));
  		for(int i=0;i<res.index;i++)
  		{
  			int doc = res.list[i];
  			SortGroupVal buff = new SortGroupVal();
  			buff.groupbuff.append(String.valueOf(doc));
  			buff.groupbuff.append(UniqConfig.GroupJoinString());
  			buff.groupbuff.append(String.valueOf(key));
  
  			for (int j = 0; j < fields.length; j++) {
  				buff.groupbuff.append(UniqConfig.GroupJoinString());
  				buff.groupbuff.append(EncodeUtils.encode("-"));
  			}
  			buff.sortString="0";
  			SelectDetailRow newrow = SelectDetailRow.INSTANCE(doc, doc);
  			newrow.setKey(new ColumnKey(buff.groupbuff.toString()));
  			newrow.colVal=buff.sortString;
  			QueuePutUtils.put2QueueDetail(newrow, topItems, this.parse.limit_offset,defcmp);
  		}
  		return topItems;
  	}
  
  
  	
  	private ShardDetailSelectDetailRowStringCompare defcmp=new ShardDetailSelectDetailRowStringCompare("string", true);
  	
  	private NamedList toNameList(PriorityQueue<SelectDetailRow> topItems) {
  		java.util.ArrayList<SelectDetailRow> recommendations = new ArrayList<SelectDetailRow>(topItems.size());
  		recommendations.addAll(topItems);
  		Collections.sort(recommendations,defcmp);
  		Integer index = 0;
  		NamedList res = new NamedList();
  		res.add("count", recordCount.toNamedList());
  		
  		ConcurrentHashMap<Long,String> cache=null;
  		boolean issetCrc=this.parse.crcOutputSet!=null;
  		long crckey=this.getkeyCrc();
  		if(issetCrc)
  		{
  			synchronized (MdrillUtils.CRC_CACHE_SIZE) {
  				cache=MdrillUtils.CRC_CACHE_SIZE.get(this.parse.crcOutputSet+"@"+crckey);
  				if(cache==null)
  				{
  					cache=new ConcurrentHashMap<Long,String>();
  					MdrillUtils.CRC_CACHE_SIZE.put(this.parse.crcOutputSet+"@"+crckey, cache);
  				}
  			}
  			
  		}
  		
  		ArrayList<Object> list=new ArrayList<Object>();
  
  		for (SelectDetailRow kv : recommendations) {
  			if (index >= this.parse.offset) {
  				if(issetCrc)
  				{
  					kv.ToCrcSet(cache);
  				}
  				list.add(kv.toNamedList());
  			}
  			index++;
  		}
  		res.add("list", list);
  		return res;
  	}
  	
  	public static class SortGroupVal{
  		public StringBuffer groupbuff=new StringBuffer();
  		public String sortString;
  	}
  	
  }
  