All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.scudata.parallel.ClusterMemoryTable Maven / Gradle / Ivy

Go to download

SPL(Structured Process Language) A programming language specially for structured data computing.

There is a newer version: 20241126
Show newest version
package com.scudata.parallel;

import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Externalizable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;

import com.scudata.array.IArray;
import com.scudata.common.MessageManager;
import com.scudata.common.RQException;
import com.scudata.dm.BaseRecord;
import com.scudata.dm.ComputeStack;
import com.scudata.dm.Context;
import com.scudata.dm.Current;
import com.scudata.dm.DataStruct;
import com.scudata.dm.Env;
import com.scudata.dm.IResource;
import com.scudata.dm.IndexTable;
import com.scudata.dm.JobSpace;
import com.scudata.dm.JobSpaceManager;
import com.scudata.dm.ListBase1;
import com.scudata.dm.Record;
import com.scudata.dm.ResourceManager;
import com.scudata.dm.Sequence;
import com.scudata.dm.Table;
import com.scudata.dm.cursor.ICursor;
import com.scudata.dm.cursor.MemoryCursor;
import com.scudata.dm.cursor.MultipathCursors;
import com.scudata.dm.op.New;
import com.scudata.dm.op.Operable;
import com.scudata.dm.op.Operation;
import com.scudata.dm.op.Select;
import com.scudata.dw.MemoryTable;
import com.scudata.expression.Expression;
import com.scudata.expression.Function;
import com.scudata.expression.FunctionLib;
import com.scudata.resources.EngineMessage;
import com.scudata.util.HashUtil;
import com.scudata.util.Variant;

/**
 * ??Ⱥ?ڱ?
 * @author RunQian
 *
 */
public class ClusterMemoryTable extends Operable implements IClusterObject, IResource, Externalizable {
	private static final long serialVersionUID = 0x07015403;
	
	private Cluster cluster;
	
	// ????Ҫ???????ڽڵ???ڡ??ڵ????????
	private RemoteMemoryTable []tables;
	private boolean isDistributed; // ?Ƿ?ֲ??ڱ????ֲ??ļ????߷ֶ???Ϊ?ֲ??ڱ?
	
	private Expression distribute; // ?ֲ?????ʽ??????Ϊ??
	private String []sortedColNames; // ???????????ֶ?
	private DataStruct distDs; // ????ֲ?ʱ?õı???ʽ
	
	private RemoteMemoryTable []sortedTables; // ?????????????????
	private int partCount; // ??ǰ?ڱ???????????????
	private int []partIndex; // ÿ????????Ӧ??Զ???ڱ???????
	
	public ClusterMemoryTable() {
	}
	
	public ClusterMemoryTable(Cluster cluster, RemoteMemoryTable []tables, boolean isDistributed) {
		this.cluster = cluster;
		this.tables = tables;
		this.isDistributed = isDistributed;
	}
	
	// ??ά????switch??joinʱ???ȶԽڵ??????????????ֵ????
	private void prepareFind(Context ctx) {
		if (sortedTables != null) {
			return;
		}
		
		RemoteMemoryTable []tables = this.tables;
		if (distribute == null) {
			String str = tables[0].getDistribute();
			if (str != null && str.length() > 0) {
				distribute = new Expression(str);
			}
		}
		
		if (distribute != null) {
			for (RemoteMemoryTable table : tables) {
				if (table.getPart() < 1) {
					distribute = null;
					break;
				}
			}
		}
		
		int count = tables.length;
		sortedTables = new RemoteMemoryTable[count];
		System.arraycopy(tables, 0, sortedTables, 0, count);
		
		if (distribute == null) {
			// ??????ֵ????
			Comparator cmp = new Comparator() {
				public int compare(RemoteMemoryTable o1, RemoteMemoryTable o2) {
					return Variant.compare(o1.getStartKeyValue(), o2.getStartKeyValue());
				}
			};
			
			Arrays.sort(sortedTables, cmp);
		} else {
			// ??????????
			Comparator cmp = new Comparator() {
				public int compare(RemoteMemoryTable o1, RemoteMemoryTable o2) {
					return o1.getPart() <= o2.getPart() ? -1 : 1;
				}
			};
			
			Arrays.sort(sortedTables, cmp);
			partCount = sortedTables[count - 1].getPart();
			partIndex = new int[partCount + 1];
			for (int i = 0; i < partCount; ++i) {
				partIndex[i] = -1;
			}
			
			for (int i = 0; i < count; ++i) {
				partIndex[sortedTables[i].getPart()] = i;
			}

			// ???ɼ???????õ????ݽṹ
			if (sortedColNames != null) {
				distDs = new DataStruct(sortedColNames);
			} else {
				ArrayList list = new ArrayList();
				distribute.getUsedFields(ctx, list);
				if (list.size() != 0) {
					String []names = new String[list.size()];
					list.toArray(names);
					distDs = new DataStruct(names);
				}
			}
		}
	}
	
	public boolean isDistributed() {
		return isDistributed;
	}
	
	public Expression getDistribute() {
		return distribute;
	}

	public void setDistribute(Expression distribute) {
		this.distribute = distribute;
	}
	
	public String[] getSortedColNames() {
		return sortedColNames;
	}

	public void setSortedColNames(String[] sortedColNames) {
		this.sortedColNames = sortedColNames;
	}
	
	public int getProxyId(int seq) {
		return tables[seq].getProxyId();
	}
	
	public int[] getProxyIds() {
		int len = tables.length;
		int ids[] = new int[len];
		for (int i = 0; i < len; i++) {
			ids[i] = tables[i].getProxyId();
		}
		return ids;
	}
	
	// ȡ??Ⱥ?ڱ??ڵ?ǰ?ڵ???϶?Ӧ???ڱ???proxyId
	public int getCurrentClusterProxyId() {
		HostManager hm = HostManager.instance();
		String host = hm.getHost();
		int port = hm.getPort();
		int count = cluster.getUnitCount();
		
		for (int i = 0; i < count; ++i) {
			if (cluster.getHost(i).equals(host) && cluster.getPort(i) == port) {
				return tables[i].getProxyId();
			}
		}
		
		return -1;
	}
	
	public Cluster getCluster() {
		return cluster;
	}
	
	public void writeExternal(ObjectOutput out) throws IOException {
		out.writeObject(cluster);
		out.writeObject(tables);
		out.writeBoolean(isDistributed);
		
		String exp = null;
		if (distribute != null) {
			exp = distribute.toString();
		}
		
		out.writeObject(exp);
		out.writeObject(sortedColNames);
	}
	
	public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
		cluster = (Cluster)in.readObject();
		tables = (RemoteMemoryTable [])in.readObject();
		isDistributed = in.readBoolean();
		
		String exp = (String)in.readObject();
		if (exp != null) {
			distribute = new Expression(exp);
		}
		
		sortedColNames = (String[])in.readObject();
	}
	
	/**
	 * k.row(T)
	 * @param key ?????ҵ??????ֶε?ֵ
	 * @return
	 */
	public BaseRecord getRow(Object key) {
		BaseRecord r = null;
		Cluster cluster = this.cluster;
		int count = cluster.getUnitCount();
		if (!isDistributed) {
			count = 1;
		}
		
		for (int i = 0; i < count; ++i) {
			UnitClient client = new UnitClient(cluster.getHost(i), cluster.getPort(i));			
			try {
				UnitCommand command = new UnitCommand(UnitCommand.GET_MT_ROW);
				command.setAttribute("jobSpaceId", cluster.getJobSpaceId());
				command.setAttribute("proxyId", getProxyId(i));
				command.setAttribute("key", key);
				Response response = client.send(command);
				r = (BaseRecord)response.checkResult();
				if (r != null) break;//ֻҪ?ҵ??˾ͷ???
			} finally {
				client.close();
			}
		}
		
		return r;
	}

	public static Response executeGetRow(HashMap attributes) {
		String jobSpaceID = (String)attributes.get("jobSpaceId");
		Integer proxyId = (Integer)attributes.get("proxyId");
		Object key = attributes.get("key");
		
		try {
			JobSpace js = JobSpaceManager.getSpace(jobSpaceID);
			ResourceManager rm = js.getResourceManager();
			TableProxy table = (TableProxy)rm.getProxy(proxyId.intValue());
			return new Response(table.getRow(key, null));
		} catch (Exception e) {
			Response response = new Response();
			response.setException(e);
			return response;
		}
	}
		
	//?????ij???ֻ?û?гɹ?????????δ?????
	public boolean createIndex(Integer capacity, String opt) {
		Cluster cluster = this.cluster;
		int count = cluster.getUnitCount();
		boolean result = true;
		
		for (int i = 0; i < count; ++i) {
			UnitClient client = new UnitClient(cluster.getHost(i), cluster.getPort(i));
			
			try {
				UnitCommand command = new UnitCommand(UnitCommand.CREATE_MT_INDEX);
				command.setAttribute("jobSpaceId", cluster.getJobSpaceId());
				command.setAttribute("proxyId", getProxyId(i));
				command.setAttribute("capacity", capacity);
				command.setAttribute("opt", opt);
				Response response = client.send(command);
				result &= (Boolean)response.checkResult();
			} finally {
				client.close();
			}
		}		
		return result;
	}
	
	public static Response executeCreateIndex(HashMap attributes) {
		String jobSpaceID = (String)attributes.get("jobSpaceId");
		Integer proxyId = (Integer)attributes.get("proxyId");
		Integer capacity = (Integer)attributes.get("capacity");
		String opt = (String)attributes.get("opt");
		
		try {
			JobSpace js = JobSpaceManager.getSpace(jobSpaceID);
			ResourceManager rm = js.getResourceManager();
			TableProxy table = (TableProxy)rm.getProxy(proxyId.intValue());
			table.createIndex(capacity, opt);
			return new Response(Boolean.TRUE);
		} catch (Exception e) {
			Response response = new Response();
			response.setException(e);
			return response;
		}
	}
	
	public Table dup() {
		Cluster cluster = this.cluster;
		int count = cluster.getUnitCount();
		if (!isDistributed) {
			count = 1;
		}
		
		Table mt = null;
		for (int i = 0; i < count; ++i) {
			UnitClient client = new UnitClient(cluster.getHost(i), cluster.getPort(i));			
			try {
				UnitCommand command = new UnitCommand(UnitCommand.DUP_CLUSTER_MT);
				command.setAttribute("jobSpaceId", cluster.getJobSpaceId());
				command.setAttribute("proxyId", getProxyId(i));
				Response response = client.send(command);
				Table cur = (Table)response.checkResult();
				if (mt != null) {
					mt.append(cur, null);
				} else {
					mt = cur;
				}
			} finally {
				client.close();
			}
		}
		
		return mt;
	}

	public static Response executeDup(HashMap attributes) {
		String jobSpaceID = (String)attributes.get("jobSpaceId");
		Integer proxyId = (Integer)attributes.get("proxyId");
		
		try {
			JobSpace js = JobSpaceManager.getSpace(jobSpaceID);
			ResourceManager rm = js.getResourceManager();
			TableProxy table = (TableProxy)rm.getProxy(proxyId.intValue());
			return new Response(table.getTable());
		} catch (Exception e) {
			Response response = new Response();
			response.setException(e);
			return response;
		}
	}
	
	public static ClusterMemoryTable dupLocal(Cluster cluster, Table table) {
		int count = cluster.getUnitCount();
		RemoteMemoryTable[] tables = new RemoteMemoryTable[count];
		int recordCount = table.length();
		int []seqs = table.dataStruct().getPKIndex();
		int keyCount = seqs == null ? 0 : seqs.length;
		
		Object keyValue = null;
		if (keyCount == 1) {
			if(recordCount > 0) {
				BaseRecord r = table.getRecord(1);
				keyValue = r.getNormalFieldValue(seqs[0]);
			}
		} else if (keyCount > 1) {
			Object []vals = new Object[keyCount];
			keyValue = vals;
			if(recordCount > 0) {
				BaseRecord r = table.getRecord(1);
				for (int i = 0; i < keyCount; ++i) {
					vals[i] = r.getNormalFieldValue(seqs[i]);
				}
			}
		}
		
		for (int i = 0; i < count; ++i) {
			String host = cluster.getHost(i);
			int port = cluster.getPort(i);
			UnitClient client = new UnitClient(host, port);			
			try {
				UnitCommand command = new UnitCommand(UnitCommand.DUP_LOCAL_MT);
				command.setAttribute("jobSpaceId", cluster.getJobSpaceId());
				command.setAttribute("table", table);
				command.setAttribute("unit", new Integer(i));
				Response response = client.send(command);
				Integer proxyId = (Integer)response.checkResult();
				tables[i] = new RemoteMemoryTable(host, port, proxyId, recordCount);

				if (keyCount > 0) {
					tables[i].setStartKeyValue(keyValue, keyCount);
				}
				
				if (table instanceof MemoryTable) {
					MemoryTable mt = (MemoryTable)table;
					tables[i].setDistribute(mt.getDistribute(), mt.getPart());
				}
			} finally {
				client.close();
			}
		}
		
		return new ClusterMemoryTable(cluster, tables, false);
	}
	
	public static Response executeDupLocal(HashMap attributes) {
		String jobSpaceID = (String)attributes.get("jobSpaceId");
		Table table = (Table)attributes.get("table");
		Integer unit = (Integer)attributes.get("unit");
		
		try {
			JobSpace js = JobSpaceManager.getSpace(jobSpaceID);
			ResourceManager rm = js.getResourceManager();
			IProxy proxy = new TableProxy(table, unit);
			rm.addProxy(proxy);
			return new Response(new Integer(proxy.getProxyId()));
		} catch (Exception e) {
			Response response = new Response();
			response.setException(e);
			return response;
		}
	}
	
	public ClusterCursor cursor(Expression []exps, String []names, Expression filter, int segCount, String opt, Context ctx) {
		Cluster cluster = this.cluster;
		int count = cluster.getUnitCount();
		int[] cursorProxyIds = new int[count];
		boolean isSeg = !isDistributed;
		
		String []fieldExps = null;
		if (exps != null) {
			int fcount = exps.length;
			fieldExps = new String[fcount];
			for (int i = 0; i < fcount; ++i) {
				fieldExps[i] = exps[i].toString();
			}
		}
		
		for (int i = 0; i < count; ++i) {
			UnitClient client = new UnitClient(cluster.getHost(i), cluster.getPort(i));
			try {
				UnitCommand command = new UnitCommand(UnitCommand.CREATE_MT_CURSOR);
				command.setAttribute("jobSpaceId", cluster.getJobSpaceId());
				command.setAttribute("proxyId", getProxyId(i));
				
				command.setAttribute("fieldExps", fieldExps);
				command.setAttribute("names", names);
				command.setAttribute("filter", filter == null ? null : filter.toString());
				command.setAttribute("option", opt);
				
				command.setAttribute("unit", new Integer(i));
				command.setAttribute("unitCount", new Integer(count));
				command.setAttribute("isSeg", isSeg);
				command.setAttribute("segCount", new Integer(segCount));
				
				ClusterUtil.setParams(command, exps, ctx);
				Response response = client.send(command);
				Integer id = (Integer) response.checkResult();
				cursorProxyIds[i] = id.intValue();
			} finally {
				client.close();
			}
		}
		
		ClusterCursor result = new ClusterCursor(this, cursorProxyIds, isDistributed);
		result.setDistribute(distribute);
		result.setSortedColNames(sortedColNames);
		return result;
	}
		
	public static Response executeCreateCursor(HashMap attributes) {
		String jobSpaceID = (String)attributes.get("jobSpaceId");
		Integer proxyId = (Integer)attributes.get("proxyId");
		String []fieldExps = (String[])attributes.get("fieldExps");
		String []names = (String[])attributes.get("names");
		String filter = (String)attributes.get("filter");
		String option = (String)attributes.get("option");
		
		Integer unit = (Integer) attributes.get("unit");
		int unitCount = (Integer)attributes.get("unitCount");
		boolean isSeg = (Boolean)attributes.get("isSeg");
		int segCount = (Integer)attributes.get("segCount");
		
		try {
			JobSpace js = JobSpaceManager.getSpace(jobSpaceID);
			Context ctx = ClusterUtil.createContext(js, attributes);
			ResourceManager rm = js.getResourceManager();
			TableProxy tp = (TableProxy)rm.getProxy(proxyId.intValue());
			Table table = tp.getTable();
			
			ICursor cursor;
			int len = table.length();
			int start = 1;
			int end = len + 1; // ??????
			
			// ?ڵ????????з?
			if (isSeg) {
				int blockSize = len / unitCount;
				start = blockSize * unit + 1;
				if (unit + 1 != unitCount) {
					end = blockSize + start;
				}
			}
			
			if (option != null && option.indexOf('m') != -1) {
				if (segCount < 2) {
					segCount = Env.getCursorParallelNum();
				}
				
				len = end - start;
				if (segCount > 1 && segCount < len) {
					// ?ڵ???ϲ?????·?α?
					int blockSize = len / segCount;
					ICursor []cursors = new ICursor[segCount];
					for (int i = 1; i <= segCount; ++i) {
						int start2 = blockSize * (i - 1) + start;
						int end2;
						
						if (i == segCount) {
							end2 = end;
						} else {
							end2 = start2 + blockSize;
						}
						
						cursors[i - 1] = new MemoryCursor(table, start2, end2);
					}
					
					cursor = new MultipathCursors(cursors, ctx);
				} else {
					cursor = new MemoryCursor(table, start, end);
				}
			} else {
				cursor = new MemoryCursor(table, start, end);
			}
			
			if (names != null) {
				int fcount = names.length;
				Expression []exps = new Expression[fcount];
				for (int i = 0; i < fcount; ++i) {
					exps[i] = new Expression(ctx, fieldExps[i]);
				}
				
				New newOp = new New(exps, names, null);
				cursor.addOperation(newOp, ctx);
			}
			
			if (filter != null) {
				Expression filterExp = new Expression(ctx, filter);
				Select select = new Select(filterExp, null);
				cursor.addOperation(select, ctx);
			}
			
			IProxy proxy = new CursorProxy(cursor, unit);
			rm.addProxy(proxy);
			return new Response(new Integer(proxy.getProxyId()));			
		} catch (Exception e) {
			Response response = new Response();
			response.setException(e);
			return response;
		}
	}
	
	public static ClusterMemoryTable memory(Cluster cluster, String varName) {
		int count = cluster.getUnitCount();
		RemoteMemoryTable[] tables = new RemoteMemoryTable[count];
		
		for (int i = 0; i < count; ++i) {
			UnitClient client = new UnitClient(cluster.getHost(i), cluster.getPort(i));
			UnitCommand command = new UnitCommand(UnitCommand.MEMORY_TABLE);
			command.setAttribute("jobSpaceId", cluster.getJobSpaceId());
			command.setAttribute("varName", varName);
			command.setAttribute("unit", new Integer(i));
			
			Response response = client.send(command);
			tables[i] = (RemoteMemoryTable)response.checkResult();
		}

		// ?????????¼??????ֵ??ͬ????Ϊ?Ƿֲ???
		Object keyValue1 = tables[0].getStartKeyValue();
		Object keyValue2 = tables[1].getStartKeyValue();
		boolean b = count > 1 && !Variant.isEquals(keyValue1, keyValue2);
		return new ClusterMemoryTable(cluster, tables, b);
	}
	
	public static Response executeMemory(HashMap attributes) {
		String jobSpaceID = (String)attributes.get("jobSpaceId");
		String varName = (String)attributes.get("varName");
		Integer unit = (Integer)attributes.get("unit");
		
		// ??varName??????ʽ???㣬???Ӧ??Ϊ????
		JobSpace js = JobSpaceManager.getSpace(jobSpaceID);
		Context ctx = new Context();
		ctx.setJobSpace(js);
		
		try {
			Expression exp = new Expression(ctx, varName);
			Object val = exp.calculate(ctx);
			MemoryTable mt;
			
			if (val instanceof MemoryTable) {
				mt = (MemoryTable)val;
			} else if (val instanceof Table) {
				mt = new MemoryTable((Table)val);
			} else if (val instanceof Sequence) {
				Sequence seq = (Sequence)val;
				Table table = seq.derive("o");
				mt = new MemoryTable(table);
			} else {
				MessageManager mm = EngineMessage.get();
				throw new RQException("memory" + mm.getMessage("function.paramTypeError"));
			}
			
			ResourceManager rm = js.getResourceManager();
			IProxy proxy = new TableProxy(mt, unit);
			rm.addProxy(proxy);
			
			RemoteMemoryTable rmt = newRemoteMemoryTable(proxy.getProxyId(), mt);
			return new Response(rmt);
		} catch (Exception e) {
			Response response = new Response();
			response.setException(e);
			return response;
		}
	}

	// ȡ????????
	private int getKeyCount() {
		return tables[0].getKeyCount();
	}
	
	private Sequence[] getRows(Sequence[] keyValues, String[] fieldExps, String[] fieldNames) {
		RemoteMemoryTable []sortedTables = this.sortedTables;
		int count = sortedTables.length;
		Sequence []result = new Sequence[count];
		
		for (int i = 0; i < count; ++i) {
			RemoteMemoryTable rmt = sortedTables[i];
			UnitClient client = new UnitClient(rmt.getHost(), rmt.getPort());
			
			try {
				UnitCommand command = new UnitCommand(UnitCommand.GET_MT_ROWS);
				command.setAttribute("jobSpaceId", cluster.getJobSpaceId());
				command.setAttribute("proxyId", rmt.getProxyId());
				command.setAttribute("keyValues", keyValues[i]);
				command.setAttribute("fieldExps", fieldExps);
				command.setAttribute("fieldNames", fieldNames);
				
				Response response = client.send(command);
				result[i] = (Sequence)response.checkResult();
			} finally {
				client.close();
			}
		}
		
		return result;
	}
	
	public static Response executeGetRows(HashMap attributes) {
		String jobSpaceID = (String)attributes.get("jobSpaceId");
		Integer proxyId = (Integer)attributes.get("proxyId");
		Sequence keyValues = (Sequence)attributes.get("keyValues");
		String []fieldExps = (String [])attributes.get("fieldExps");
		String []fieldNames = (String [])attributes.get("fieldNames");
		
		JobSpace js = JobSpaceManager.getSpace(jobSpaceID);
		Context ctx = ClusterUtil.createContext(js);
		Expression []newExps = null;
		if (fieldExps != null) {
			int count = fieldExps.length;
			newExps = new Expression[count];
			for (int i = 0; i < count; ++i) {
				newExps[i] = new Expression(ctx, fieldExps[i]);
			}
		}
		
		try {
			ResourceManager rm = js.getResourceManager();
			TableProxy tableProxy = (TableProxy)rm.getProxy(proxyId.intValue());
			Table table = tableProxy.getTable();
			Sequence result = getRows(table, keyValues, newExps, fieldNames, ctx);
			return new Response(result);
		} catch (Exception e) {
			Response response = new Response();
			response.setException(e);
			return response;
		}
	}
	
	private static Sequence getRows(Table table, Sequence keySeq,
			Expression[] newExps, String[] newNames, Context ctx) {
		if (keySeq == null || keySeq.length() == 0) {
			return new Sequence(0);
		}

		String[] pkNames = table.getPrimary();
		int pkCount = pkNames.length;
		IndexTable indexTable = table.getIndexTable();
		if (indexTable == null) {
			table.createIndexTable(null);
			indexTable = table.getIndexTable();
		}

		int len = keySeq.length();
		Sequence result = new Sequence(len);

		if (pkCount == 1) {
			for (int i = 1; i <= len; ++i) {
				Object pk = keySeq.getMem(i);
				BaseRecord r = (BaseRecord) indexTable.find(pk);
				result.add(r);
			}
		} else {
			for (int i = 1; i <= len; ++i) {
				Object[] pks = (Object[])keySeq.getMem(i);
				BaseRecord r = (BaseRecord) indexTable.find(pks);
				result.add(r);
			}
		}

		if (newExps == null || newExps.length == 0) {
			return result;
		}
		
		IArray mems = result.getMems();
		int colCount = newExps.length;
		DataStruct ds = new DataStruct(newNames);
		ComputeStack stack = ctx.getComputeStack();
		Current current = new Current(result);
		stack.push(current);
		
		try {
			for (int i = 1; i <= len; ++i) {
				if (mems.get(i) != null) {
					current.setCurrent(i);
					Record r = new Record(ds);
					
					for (int c = 0; c < colCount; ++c) {
						r.setNormalFieldValue(c, newExps[c].calculate(ctx));
					}
					
					mems.set(i, r);
				} else {
					mems.set(i, null);
				}
			}
		} finally {
			stack.pop();
		}
		
		return result;
	}
	
	/**
	 * ??????ֵȡ??¼
	 * @param keySeq ????ֵ????
	 * @param newExps ???صļ????ֶα???ʽ?????򷵻?Դ??¼
	 * @param newNames
	 * @param ctx
	 * @return
	 */
	public Sequence getRows(Sequence keySeq, String[] newExps, String[] newNames, Context ctx) {
		prepareFind(ctx);
		
		IArray mems = keySeq.getMems();
		int srcLen = mems.size();
		HashUtil hashUtil = new HashUtil(srcLen);
		final int INIT_GROUPSIZE = HashUtil.getInitGroupSize();
		ListBase1 []groups = new ListBase1[hashUtil.getCapacity()];
		Sequence ids = new Sequence(hashUtil.getCapacity());
		
		int keyCount = getKeyCount();
		if (keyCount == 0) {
			MessageManager mm = EngineMessage.get();
			throw new RQException(mm.getMessage("ds.lessKey"));
		}
		
		if (keyCount == 1) {
			for (int i = 1; i <= srcLen; ++i) {
				Object mem = mems.get(i);
				int hash = hashUtil.hashCode(mem);
				if (groups[hash] == null) {
					Object []objs = new Object[2];
					objs[0] = mem;
					ids.add(objs);
	
					groups[hash] = new ListBase1(INIT_GROUPSIZE);
					groups[hash].add(objs);
				} else {
					int index = HashUtil.bsearch_a(groups[hash], mem);
					if (index < 1) {
						Object []objs = new Object[2];
						objs[0] = mem;
						ids.add(objs);
	
						groups[hash].add(-index, objs);
					}
				}
			}
		} else {
			int count = keyCount + 1;
			for (int i = 1; i <= srcLen; ++i) {
				Object []mem = (Object[])mems.get(i);
				int hash = hashUtil.hashCode(mem);
				if (groups[hash] == null) {
					Object []objs = new Object[count];
					System.arraycopy(mem, 0, objs, 0, keyCount);
					objs[keyCount] = mem;
					ids.add(objs);

					groups[hash] = new ListBase1(INIT_GROUPSIZE);
					groups[hash].add(objs);
				} else {
					int index = HashUtil.bsearch_a(groups[hash], mem, keyCount);
					if (index < 1) {
						Object []objs = new Object[count];
						System.arraycopy(mem, 0, objs, 0, keyCount);
						objs[keyCount] = mem;
						ids.add(objs);

						groups[hash].add(-index, objs);
					}
				}
			}
		}

		// ?????????н??з???
		Sequence []seqs = group(ids, ctx);
		
		int gcount = seqs.length;
		Sequence []keySeqs = new Sequence[gcount];
		for (int g = 0; g < gcount; ++g) {
			Sequence seq = seqs[g];
			IArray curMems = seq.getMems();
			int len = curMems.size();
			Sequence tmp = new Sequence(len);
			keySeqs[g] = tmp;
			
			int keyIndex = keyCount == 1 ? 0 : keyCount;
			for (int i = 1; i <= len; ++i) {
				Object []objs = (Object[])curMems.get(i);
				tmp.add(objs[keyIndex]);
			}
		}

		Sequence []tables = getRows(keySeqs, newExps, newNames);

		// ?ѷ??ص?tables?????????й????????????ϲ???ͬһ??table??
		//DataStruct ds = new DataStruct(newNames);
		for (int g = 0; g < gcount; ++g) {
			Sequence seq = seqs[g];
			IArray curMems = seq.getMems();
			int len = curMems.size();
			Sequence curTable = tables[g];
			for (int i = 1; i <= len; ++i) {
				Object []objs = (Object[])curMems.get(i);
				BaseRecord r = (BaseRecord)curTable.get(i);
				objs[keyCount] = r;

				//if (r != null) r.setDataStruct(ds);
			}
		}

		Sequence result = new Sequence(srcLen);
		if (keyCount == 1) {
			for (int i = 1; i <= srcLen; ++i) {
				Object mem = mems.get(i);
				int hash = hashUtil.hashCode(mem);
				int index = HashUtil.bsearch_a(groups[hash], mem);
				Object []objs = (Object[])groups[hash].get(index);
				result.add(objs[1]);
			}
		} else {
			for (int i = 1; i <= srcLen; ++i) {
				Object []mem = (Object[])mems.get(i);
				int hash = hashUtil.hashCode(mem);
				int index = HashUtil.bsearch_a(groups[hash], mem, keyCount);
				Object []objs = (Object[])groups[hash].get(index);
				result.add(objs[keyCount]);
			}
		}

		return result;
	}
	
	// ?????????а??ڵ?????з???
	private Sequence[] group(Sequence result, Context ctx) {
		RemoteMemoryTable []tables = this.sortedTables;
		int groupCount = tables.length;
		
		// ??????Ƿֲ??ڱ?ֻ?ӵ?һ???ڵ???ң?
		if (!isDistributed) {
			Sequence []seqs = new Sequence[groupCount];
			seqs[0] = new Sequence(result);
			for (int i = 1; i < groupCount; ++i) {
				seqs[i] = new Sequence(0);
			}
			
			return seqs;
		}
		
		IArray mems = result.getMems();
		int len = mems.size();
		
		Sequence []seqs = new Sequence[groupCount];
		int initCount = len / groupCount + 10;
		for (int i = 0; i < groupCount; ++i) {
			seqs[i] = new Sequence(initCount);
		}

		if (distDs == null) {
			int keyCount = getKeyCount();
			int last = groupCount - 1;
			if (keyCount == 1) {
				Object []startVals = new Object[groupCount];
				for (int i = 0; i < groupCount; ++i) {
					startVals[i] = tables[i].getStartKeyValue();
				}
				
				Next:
				for (int i = 1; i <= len; ++i) {
					Object []objs = (Object[])mems.get(i);
					for (int g = 1; g < groupCount; ++g) {
						int cmp = Variant.compare(startVals[g], objs[0]);
						if (cmp > 0) {
							seqs[g - 1].add(objs);
							continue Next;
						} else if (cmp == 0) {
							seqs[g].add(objs);
							continue Next;
						}
					}
					
					seqs[last].add(objs);
				}
			} else {
				Object [][]startVals = new Object[groupCount][];
				for (int i = 0; i < groupCount; ++i) {
					startVals[i] = (Object [])tables[i].getStartKeyValue();
				}
						
				Next:
				for (int i = 1; i <= len; ++i) {
					Object []objs = (Object[])mems.get(i);
					for (int g = 1; g < groupCount; ++g) {
						int cmp = Variant.compareArrays(startVals[g], objs, keyCount);
						if (cmp > 0) {
							seqs[g - 1].add(objs);
							continue Next;
						} else if (cmp == 0) {
							seqs[g].add(objs);
							continue Next;
						}
					}
					
					seqs[last].add(objs);
				}
			}
		} else {
			int partCount = this.partCount; // ??ǰ?ڱ???????????????
			int []partIndex = this.partIndex; // ÿ????????Ӧ??Զ???ڱ???????
			Expression distribute = this.distribute;
			int keyCount = distDs.getFieldCount();
			Record r = new Record(distDs);
			ComputeStack stack = ctx.getComputeStack();
			stack.push(r);
			
			try {
				for (int i = 1; i <= len; ++i) {
					Object []objs = (Object[])mems.get(i);
					for (int k = 0; k < keyCount; ++k) {
						r.setNormalFieldValue(k, objs[k]);
					}
					
					Object obj = distribute.calculate(ctx);
					if (obj instanceof Number) {
						int n = ((Number)obj).intValue();
						if (n > 0 && n <= partCount) {
							seqs[partIndex[n]].add(objs);
						}
					}
				}
			} finally {
				stack.pop();
			}
		}
		
		return seqs;
	}
	
	public static RemoteMemoryTable newRemoteMemoryTable(int proxy, Table table) {
		int recordCount = table.length();
		int []seqs = table.dataStruct().getPKIndex();
		int keyCount = seqs == null ? 0 : seqs.length;
		
		Object keyValue = null;
		if (keyCount == 1) {
			if(recordCount > 0) {
				BaseRecord r = table.getRecord(1);
				keyValue = r.getNormalFieldValue(seqs[0]);
			}
		} else if (keyCount > 1) {
			Object []vals = new Object[keyCount];
			keyValue = vals;
			if(recordCount > 0) {
				BaseRecord r = table.getRecord(1);
				for (int i = 0; i < keyCount; ++i) {
					vals[i] = r.getNormalFieldValue(seqs[i]);
				}
			}
		}
		
		HostManager hm = HostManager.instance();
		String host = hm.getHost();
		int port = hm.getPort();
		RemoteMemoryTable rmt = new RemoteMemoryTable(host, port, proxy, recordCount);
		
		if (keyCount > 0) {
			rmt.setStartKeyValue(keyValue, keyCount);
		}
		
		if (table instanceof MemoryTable) {
			MemoryTable mt = (MemoryTable)table;
			rmt.setDistribute(mt.getDistribute(), mt.getPart());
		}
		
		return rmt;
	}
	
	public Operable addOperation(Operation op, Context ctx) {
		Cluster cluster = getCluster();
		int count = cluster.getUnitCount();
		Function function = op.getFunction();
		String functionName = function.getFunctionName();
		String option = function.getOption();
		String param = function.getParamString();
		
		for (int i = 0; i < count; ++i) {
			UnitClient client = new UnitClient(cluster.getHost(i), cluster.getPort(i));
			
			try {
				UnitCommand command = new UnitCommand(UnitCommand.MT_ADD_OPERATION);
				command.setAttribute("jobSpaceId", cluster.getJobSpaceId());
				command.setAttribute("proxyId", new Integer(getProxyId(i)));
				//command.setAttribute("unit", new Integer(i));
				command.setAttribute("functionName", functionName);
				command.setAttribute("option", option);
				command.setAttribute("param", param);
				ClusterUtil.setParams(command, function, ctx);
				
 				Response response = client.send(command);
				response.checkResult();
			} finally {
				client.close();
			}
		}
		
		return this;
	}
	
	public static Response executeAddOperation(HashMap attributes) {
		String jobSpaceID = (String)attributes.get("jobSpaceId");
		Integer proxyId = (Integer)attributes.get("proxyId");
		//Integer unit = (Integer)attributes.get("unit");
		String functionName = (String)attributes.get("functionName");
		String option = (String)attributes.get("option");
		String param = (String)attributes.get("param");
		
		try {
			JobSpace js = JobSpaceManager.getSpace(jobSpaceID);
			Context ctx = ClusterUtil.createContext(js, attributes, functionName, option);
			
			ResourceManager rm = js.getResourceManager();
			TableProxy table = (TableProxy)rm.getProxy(proxyId.intValue());
			Object obj = FunctionLib.executeMemberFunction(table.getTable(), functionName, param, option, ctx);
			if (obj instanceof Table) {
				table.setTable((Table)obj);
			}
			
			return new Response();
		} catch (Exception e) {
			Response response = new Response();
			response.setException(e);
			return response;
		}
	}
		
	// ?رռ?Ⱥ?ڱ??ͷŽڵ????Դ
	public void close() {
		Cluster cluster = this.cluster;
		int count = cluster.getUnitCount();
		
		for (int i = 0; i < count; ++i) {
			UnitClient client = new UnitClient(cluster.getHost(i), cluster.getPort(i));			
			try {
				UnitCommand command = new UnitCommand(UnitCommand.CLOSE_MT);
				command.setAttribute("jobSpaceId", cluster.getJobSpaceId());
				command.setAttribute("proxyId", getProxyId(i));
				client.send(command);
			} finally {
				client.close();
			}
		}
	}

	public static Response executeClose(HashMap attributes) {
		String jobSpaceID = (String)attributes.get("jobSpaceId");
		Integer proxyId = (Integer)attributes.get("proxyId");
		
		try {
			JobSpace js = JobSpaceManager.getSpace(jobSpaceID);
			ResourceManager rm = js.getResourceManager();
			boolean b = rm.closeProxy(proxyId);
			return new Response(b);
		} catch (Exception e) {
			Response response = new Response();
			response.setException(e);
			return response;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy