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

com.scudata.dm.ParallelCaller Maven / Gradle / Ivy

Go to download

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

There is a newer version: 20240823
Show newest version
package com.scudata.dm;

import java.text.DecimalFormat;
import java.util.*;

import com.scudata.common.*;
import com.scudata.expression.Expression;
import com.scudata.parallel.*;
import com.scudata.server.unit.UnitServer;
import com.scudata.thread.ThreadPool;

/**
 * ʵ?ֲ??????ú???callx(dfx,??;hs;rdfx)?IJ?????????
 * ??ֻ?????hs??????ҵִ?нű?dfx???̳?????ռ䣻????ÿ????ҵ?ķ???ֵ???ɵ????С?
 * ??ҵ??????????(end msg)?????·??䣨?ܿ??ѷ?????ֻ?????????Ҳ??????÷ֻ???????ʧ?ܣ???ҵ???䵽?????÷ֻ?ʱ????Ϊ??????????
 * ȱʡ?????η??䣬????i????ҵ???䵽hs.m@r(i)??
 * rdfx???????????Ľű???????reduce????????ʡ?ԡ???????ֱ??ǵ?ǰ?ۻ?ֵ?͵?ǰ????ֵ??rdfx????ֵ????Ϊ?µ??ۻ?ֵ????ʼ?ۻ?ֵΪnull
 * ??rdfxʱ??????ֵ????ÿ???ֻ??ķ???ֵ???ɵ????У???hs?Ĵ???
 * @author Joancy
 *
 */
public class ParallelCaller extends ParallelProcess {
	// ??Ϊ?????Ӻ?nodeһ???????ͻ?????ռ?????ӣ??????㷨??ֱ????????
	// ???????㷨????ֱ??ʹ??nodes???????? ucList?еĶ??зֻ????????㷨??nodes???˷ѳ?ʼ????
	private UnitClient[] nodes = null;

	private Context ctx;
	private int activeHostCount = 0;

	private final byte TYPE_DEFAULT = 0;//ȱʡ˳?η??䣬??????ֻ?
	private final byte TYPE_ONE = 1;//һ????ҵȫ?????䣬???ķ??غ??ж???????ҵ
	private final byte TYPE_RANDOM = 2;//???????
//	private final byte TYPE_MUCH = 3;//Ԥ????Ȼ??????ҵ

	private String opt = null;

	/**
	 * ????һ?????????ö???
	 * @param dfx ???????
	 * @param hosts ?ֻ?
	 * @param ports ?˿?
	 */
	public ParallelCaller(Object dfx, String[] hosts, int[] ports) {
		super(dfx);
		if (hosts == null)
			return;// ?????߳?ִ??ʱ

		nodes = new UnitClient[hosts.length];
		for (int i = 0; i < hosts.length; i++) {
			UnitClient uc = new UnitClient(hosts[i], ports[i]);
			try {
				uc.connect();
			} catch (Exception x) {
				Logger.severe(uc + ":" + x.getMessage());
			}
			nodes[i] = uc;
		}
	}

	/**
	 * ???ü???ѡ??
	 * @param ops ѡ??
	 */
	public void setOptions(String ops) {
		this.opt = ops;
	}

	/**
	 * ?????????
	 * @return ???????ѡ???true
	 */
	public boolean isAOption() {
		return opt != null && opt.indexOf('a') != -1;
	}

	/**
	 * ֻ??һ????ҵҲ????????п??÷ֻ????κ?һ????????ɣ??ж?????????
	 * @return һ????ҵѡ???true
	 */
	public boolean is1Option() {
		return opt != null && opt.indexOf('1') != -1;
	}

	/**
	 * ȱʡ˳?η???
	 * @return ȱʡ˳?η??䷵??true
	 */
	public boolean isDefaultOption() {
		return opt == null;
	}
	/**
	 * ???ü??㻷?????????Ķ???
	 * @param ctx ??????
	 */
	public void setContext(Context ctx) {
		this.ctx = ctx;
		ctx.addResource(this);
	}

	// ?÷?????????ҷֻ?????
	private void randomUCList() {
		Sequence sortSeq = new Sequence();
		while(!ucList.isEmpty()){
			sortSeq.add(ucList.removeFirst());
		}
		Expression exp = new Expression("rand()");
		sortSeq.sort(exp, null, "o", new Context());
		for(int i=1;i<=sortSeq.length();i++){
			ucList.add((UnitClient)sortSeq.get(i));
		}
	}

	private byte getCalcType() {
		if (isAOption()) {
			return TYPE_RANDOM;
		}
		if (is1Option()) {
			return TYPE_ONE;
		}
		return TYPE_DEFAULT;
	}

	/**
	 * ִ????ҵ?????ؼ?????
	 * @return ??????
	 */
	public Object execute() {
		if (nodes == null) {
			//???????߳?ִ??
			return super.execute();
		}
		try {
			checkLiveNodes();
			checkCallerSize();

			byte calcType = getCalcType();
			Object result = null;
			switch (calcType) {
			case TYPE_ONE:
				result = executeOne();
				break;
			default:
				result = execute( calcType );
			}
			return result;
		} finally {
			closeConnects();
		}
	}
	
	/**
	 * ֻ??һ????ҵʱ??ʹ??1ѡ????䵽???зֻ???ȡ???Ľ???󷵻?
	 * @return ??????
	 */
	public Object executeOne() {
		Logger.debug("1????ҵʱ???ָ????зֻ???ȡ???Ľ??");
		ThreadPool pool = null;
		try {
			List pCallers = new ArrayList();
			ucList = new LinkedList();

			int size = nodes.length;
			// ??Ҫ?ݴ????ҳ???ķֻ????????ݴ?????
			for (int i = 0; i < size; i++) {
				UnitClient uc = nodes[i];
				if (!uc.isConnected()) {
					continue;
				}
				appendClient(uc, false);
				activeHostCount++;
			}

			Sequence argPos = new Sequence();
			argPos.add(1);
			List args = reserveResult(argPos);
//			????ҵ?ָ????еķֻ?
			for (int i = 1; i <= size; i++) {
				ProcessCaller pcaller = new ProcessCaller(args);
				pcaller.setPositions(argPos);
				pcaller.setOneOption();
				pCallers.add(pcaller);
			}

			callers.clear();
			for (ProcessCaller pc : pCallers) {
				callers.add(pc);
			}
			// ?????Ĺ????أ?ֱ???Ƿֻ?????Ŀ
			int poolSize = ucList.size();
			pool = ThreadPool.newSpecifiedInstance(poolSize);
			for (int i = 0; i < size; i++) {
				ProcessCaller pcaller = (ProcessCaller) callers.get(i);
				UnitClient uc = getClient();
				pcaller.setUnitClient(uc);
				pool.submit(pcaller);
			}
			joinCallers();

			return result;
		} catch (Throwable x) {
			if (x instanceof OutOfMemoryError) {
				Logger.severe(x);
			}
			interruptAll(null, x);

			if(x.getMessage().equals(ParallelProcess.ONE_OPTION)){
//				1ѡ???????????׳?ONE_OPTION?쳣????ϱ????ҵ??Ȼ??ֱ?ӷ??ؽ????
				return result;
			}
			throw new RuntimeException(x);
		} finally {
			if (pool != null) {
				pool.shutdown();
			}
		}
	}

	/**
	 * ȱʡ˳?η???
	 * @return ??????
	 */
	public Object execute(byte calcType) {
		String msg;
		if(calcType==TYPE_DEFAULT){
			msg = "Dispatch jobs by sorting order.";
		}else{
			msg = "Dispatch jobs on random order.";
		}
		Logger.debug( msg );
		ThreadPool pool = null;
		try {
			List pCallers = new ArrayList();
			ucList = new LinkedList();

			int size = nodes.length;
			int maxTaskNum = 0;
			HashMap ucTaskMap = new HashMap();
			// ??Ҫ?ݴ????ҳ???ķֻ????????ݴ?????
			for (int i = 0; i < size; i++) {
				UnitClient uc = nodes[i];
				if (!uc.isConnected()) {
					continue;
				}
				int maxNum = uc.getUnitMaxNum();
				if (maxNum > maxTaskNum) {
					maxTaskNum = maxNum;
				}
				ucTaskMap.put(uc.toString(), maxNum);
				appendClient(uc, false);
				activeHostCount++;
			}

			// ???ݷֻ????????ҵ????????ֻ?????ҵ????
			size = callers.size();
			for (int i = 1; i <= maxTaskNum; i++) {
				for (int n = 0; n < activeHostCount; n++) {
					UnitClient tmp = ucList.get(n);
					Integer tmpMax = ucTaskMap.get(tmp.toString());
					if (i < tmpMax) {
						// ????ķֻ???ȱʡ??¡
						appendClient(tmp);
					}
				}
			}
			
			// Ϊ?˷?ֹ??????ҵȫ?????ڵ?һ̨????ʱ??????б?û??ȫ???ճ??????˶????Ա?֤????ĸ??????Ե??ڷֻ?????
			if (reduce != null) {
				int maxIndex = nodes.length;
				result.set(maxIndex, null);
			}

			for (int i = 1; i <= size; i++) {
				Sequence argPos = new Sequence();
				argPos.add(i);
				List args;
				if (reduce != null) {
//					??ǰ??û?з???ֻ???????1?ŷֻ?ռ???طֻ?ռλ??
					args = reserveResult(argPos,1);
				} else {
//					????Ҫreduceʱ?????ؽ???????????ռλ
					args = reserveResult(argPos);
				}
				
				ProcessCaller pcaller = new ProcessCaller(args);
				if (reduce == null) {
					pcaller.setPositions(argPos);
				}
				// ?????ݴ?
				pcaller.setDispatchable(true);
				pCallers.add(pcaller);
			}

			callers.clear();
			for (ProcessCaller pc : pCallers) {
				callers.add(pc);
			}
			
			if(calcType==TYPE_RANDOM){
				randomUCList();
			}
			
			// ?????Ĺ????أ???????ҵ?????ֻ????????ҵ??????ȡС?ķ???
			int poolSize = Math.min(size, ucList.size());
			pool = ThreadPool.newSpecifiedInstance(poolSize);
			for (int i = 0; i < size; i++) {
				ProcessCaller pcaller = (ProcessCaller) callers.get(i);
				UnitClient uc = getClient();
				if (reduce != null) {
					pcaller.setReduce(reduce, accumulateLocation,currentLocation);//,ucIndex);
				}
				pcaller.setUnitClient(uc);
				pool.submit(pcaller);
			}
			joinCallers();

			if (reduce != null) {
//				??reduceʱ?????Ӹ??ֻ???reduce?Ľ??ȡ??
				for(int i=0;i reserveResult(Sequence posIndexes) {
		return reserveResult(posIndexes, null);
	}

	private List reserveResult(Sequence posIndexes, Integer ucIndex) {
		return reserveResult(callers, posIndexes, ucIndex);
	}

	private List reserveResult(ArrayList acs,
			Sequence posIndexes, Integer ucIndex) {
		List args = new ArrayList();
		for (int i = 1; i <= posIndexes.length(); i++) {
			int pos = (Integer) posIndexes.get(i);
			Caller c = acs.get(pos - 1);
			args.add(c.getArgs());
		}

		if (reduce != null) {
			if (ucIndex != null) {
				result.set(ucIndex, null);
			} else {
				result.add(null);
			}
		} else {
			for (int i = 0; i < posIndexes.length(); i++) {
				result.add(null);
			}
		}
		return args;
	}
	
//???ֻ????????ҵ??һ????ҵ?????ж????????????reduce
	class ProcessCaller extends Caller implements IResource {
		private Object reduce = null;
		private CellLocation accumulateLocation = null;
		private CellLocation currentLocation = null;
		
		private Sequence argPositions = null;
		private boolean isDispatchable = false;

		Context pcCtx = null;
		Expression pcExp = null;

		public ProcessCaller(List argList) {
			super(argList);
		}

		public void setDispatchable(boolean d) {
			isDispatchable = d;
		}
		
		public void setUnitClient(UnitClient uc) throws Exception {
			this.uc = uc;
			if (canRunOnLocal()) {
				// ??????Ա???ִ??ʱ??????Ҫ?ӷֻ???ȡ????ţ?Ҳ?????????ֻ??ij?????
				taskId = UnitServer.nextId();
				return;
			}

			Request req = new Request(Request.DFX_TASK);
			req.setAttr(Request.TASK_DfxName, dfx);
			req.setAttr(Request.TASK_ArgList, argList);
			req.setAttr(Request.TASK_SpaceId, spaceId);
			req.setAttr(Request.TASK_IsProcessCaller, true);
			req.setAttr(Request.TASK_Reduce, reduce);
			req.setAttr(Request.TASK_AccumulateLocation, accumulateLocation);
			req.setAttr(Request.TASK_CurrentLocation, currentLocation);

			Response res = uc.send(req);
			if (res.getException() != null) {
				throw res.getException();
			}
			taskId = (Integer) res.getResult();
			registResource();
		}

		private void registResource() {
			ctx.getJobSpace().addHosts(uc.getHost(), uc.getPort());
			ctx.addResource(this);
		}

		public void setReduce(Object reduce, CellLocation accumulateLocation, CellLocation currentLocation){//, int argPos) {
			this.reduce = reduce;
			this.accumulateLocation = accumulateLocation;
			this.currentLocation = currentLocation;
		}

		public void setPositions(Sequence argPos) {
			this.argPositions = argPos;
		}

		void setResponseValue(Object rVal) {
			int index = 0;
			if (reduce != null) {
			} else {
				Sequence pos = argPositions;
				Sequence val = null;
				if (rVal instanceof Sequence) {
					val = (Sequence) rVal;
				} else {
					// ??????С??host.lengthʱ??Ҳ?Dz??ö??????????????????????????????ڴ?ʱÿ̨?ֻ????һ????ҵ??
					// ???Է???ֵ????Sequence????ʱ??argPositionsֻ??Ϊһ????Ա?????У??˴???resultҲת??Ϊ
					// ֻ??һ????Ա?????С?
					val = new Sequence();
					val.add(rVal);
				}

				for (int i = 1; i <= pos.length(); i++) {
					index = (Integer) pos.get(i);
					Object tmp = null;
					if (i <= val.length()) {
						tmp = val.get(i);
					} else {
						Logger.severe(mm.getMessage("ParallelCaller.emptysub"));//"?ӳ??򷵻ص?ֵΪ?գ?");
					}
					setResult(index, tmp);
				}
			}
		}

		public void close() {
			interruptAll(this, new Exception(TERMINATE));
			if (uc != null) {
				uc.close();
			}
			ctx.removeResource(this);
		}

		// ???????ķֻ????????????·???
		private transient HashSet errorNodes = new HashSet();

		public void run() {
			if (!isDispatchable) {
				super.run();
				return;
			}

			isRunning = true;
			try {
				while (true) {
					if (isCanceled) {
						Logger.debug(mm.getMessage("ParallelProcess.canceled",
								this));
						break;
					}
					try {
						long l1 = System.currentTimeMillis();
						Logger.debug(mm.getMessage("Task.taskBegin", this));
						if (canRunOnLocal()) {
							runOnLocal( true );
						}else{
							runOnNode();
						}
						long l2 = System.currentTimeMillis();
						DecimalFormat df = new DecimalFormat("###,###");
						long lastTime = l2 - l1;
						Logger.debug(mm.getMessage("Task.taskEnd", this,
								df.format(lastTime)));// this+" ??ʼ???㡣");
						break;
					} catch (RetryException re) { // ??Ҫ???·???ֻ??쳣ʱ
						releaseClient(uc);
						if (!errorNodes.contains(uc)) {
							errorNodes.add(uc.clone());
						}
						try {
							UnitClient tmpuc = getDispatchNode(errorNodes,
									args2String(argList), re.getMessage());
							setUnitClient(tmpuc);
							Logger.debug(mm.getMessage(
									"ParallelProcess.reassign", this));
						} catch (Exception ex) {
							interruptAll(this, ex);
							break;
						}
					}
				}
			} catch (Throwable t) {
				interruptAll(this, t);
			} finally {
				releaseClient(uc);
				isRunning = false;
			}
		}
	}

	/**
	 * ??ȡһ??????ִ?еķֻ?,?????ݴ?ij??ִ???е????????????жϻ??߷ֻ??????ȣ? ???·???ֻ?
	 * 
	 * @return UnitClient ?ֻ??ͻ???
	 */
	public UnitClient getDispatchNode(HashSet errorNodes,
			String argString, String cause) throws Exception {
		if (errorNodes.size() == activeHostCount) {
			throw new Exception(mm.getMessage("ParallelProcess.exeFail",
					argString, cause));
		}
		UnitClient uc = getClient();
		while (contains(errorNodes, uc)) {
			releaseClient(uc);
			uc = getClient();
		}
		return uc;
	}

	// ?÷???ֻ?????????̶˿ں????Ƚϣ?????ͬһ???ֻ????ӽ??̣?????ͬ?ġ?
	// errorNodes.contains??Ƚ?hashKey???Ὣ?ӽ??̶˿?Ҳ???ȥ
	private boolean contains(HashSet errorNodes, UnitClient uc) {
		Iterator nodes = errorNodes.iterator();
		while (nodes.hasNext()) {
			UnitClient tmp = nodes.next();
			if (tmp.equals(uc)) {
				return true;
			}
		}
		return false;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy