package org.opencloudb.mpp; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.opencloudb.net.mysql.RowDataPacket; import org.opencloudb.route.RouteResultset; /** * Data merge service handle data Min,Max,AVG group 、order by 、limit * * @author wuzhih * */ public class DataMergeService { private static final Logger LOGGER = Logger .getLogger(DataMergeService.class); private RowDataPacketGrouper grouper = null; private RowDataPacketSorter sorter = null; private Collection<RowDataPacket> result=new LinkedList<RowDataPacket>(); // private final Map<String, DataNodeResultInf> dataNodeResultSumMap; public DataMergeService(RouteResultset rrs) { this.rrs = rrs; // dataNodeResultSumMap = new HashMap<String, DataNodeResultInf>( // rrs.getNodes().length); } /** * return merged data * * @return */ public Collection<RowDataPacket> getResults() { Collection<RowDataPacket> tmpResult = result; if (this.grouper != null) { tmpResult = grouper.getResult(); grouper = null; } if (sorter != null) { Iterator<RowDataPacket> itor = tmpResult.iterator(); while (itor.hasNext()) { sorter.addRow(itor.next()); itor.remove(); } tmpResult = sorter.getSortedResult(); sorter = null; } return tmpResult; } public void setFieldCount(int fieldCount) { this.fieldCount = fieldCount; } public RouteResultset getRrs() { return rrs; } private int fieldCount; private final RouteResultset rrs; public void onRowMetaData(Map<String, ColMeta> columToIndx, int fieldCount) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("field metadata inf:" + Arrays.toString(columToIndx.entrySet().toArray())); } int[] groupColumnIndexs = null; this.fieldCount = fieldCount; if (rrs.getOrderByCols() != null) { } if (rrs.getGroupByCols() != null) { groupColumnIndexs = (toColumnIndex(rrs.getGroupByCols(), columToIndx)); } if (rrs.isHasAggrColumn()) { List<MergeCol> mergCols = new LinkedList<MergeCol>(); if (rrs.getMergeCols() != null) { for (Map.Entry<String, Integer> mergEntry : rrs.getMergeCols() .entrySet()) { String colName = mergEntry.getKey(); ColMeta colMeta = columToIndx.get(colName); mergCols.add(new MergeCol(colMeta, mergEntry.getValue())); } } // add no alias merg column for (Map.Entry<String, ColMeta> fieldEntry : columToIndx.entrySet()) { String colName = fieldEntry.getKey().toUpperCase(); int result = MergeCol.tryParseAggCol(colName); if (result != MergeCol.MERGE_UNSUPPORT && result != MergeCol.MERGE_NOMERGE) { mergCols.add(new MergeCol(fieldEntry.getValue(), result)); } } grouper = new RowDataPacketGrouper(groupColumnIndexs, mergCols.toArray(new MergeCol[mergCols.size()])); } if (rrs.getOrderByCols() != null) { LinkedHashMap<String, Integer> orders = rrs.getOrderByCols(); OrderCol[] orderCols = new OrderCol[orders.size()]; int i=0; for (Map.Entry<String, Integer> entry:orders.entrySet()) { orderCols[i++] = new OrderCol( columToIndx.get(entry.getKey()), entry.getValue()); } sorter = new RowDataPacketSorter(orderCols); } else { result = new LinkedList<RowDataPacket>(); } } /** * process new record (mysql binary data),if data can output to client * ,return true * * @param dataNode * DN's name (data from this dataNode) * @param rowData * raw data */ public boolean onNewRecord(String dataNode, byte[] rowData) { RowDataPacket rowDataPkg = new RowDataPacket(fieldCount); rowDataPkg.read(rowData); if (grouper != null) { grouper.addRow(rowDataPkg); } else { result.add(rowDataPkg); } // todo ,if too large result set ,should store to disk return false; } private static int[] toColumnIndex(String[] columns, Map<String, ColMeta> toIndexMap) { int[] result = new int[columns.length]; for (int i = 0; i < columns.length; i++) { result[i] = toIndexMap.get(columns[i]).colIndex; } return result; } /** * release resources */ public void clear() { grouper = null; sorter = null; result = null; } } class DataNodeResultInf { public RowDataPacket firstRecord; public RowDataPacket lastRecord; public int rowCount; }