//--------------------------------------------------------------------------- // Copyright 2006-2009 // Dan Roozemond, d.a.roozemond@tue.nl, (TU Eindhoven, Netherlands) // Peter Horn, horn@math.uni-kassel.de (University Kassel, Germany) // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //--------------------------------------------------------------------------- package org.symcomp.spsd; import org.symcomp.scscp.SCSCPClient; import org.symcomp.scscp.ProcedureCall; import org.symcomp.scscp.Computation; import org.symcomp.openmath.*; import org.symcomp.notification.NotificationCenter; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.HashMap; import java.util.List; import java.util.LinkedList; import java.util.Collection; /** * the 'Simple Parallel SCSCP Dispatcher' is responsible to parallely * dispatch work to some registered systems. It is derived from SCSCPClient * to allow for uniform access. */ public class SPSD extends SCSCPClient { private List<SCSCPClient> workers; private List<AbstractSPSDHandler> handlers; public SPSD(String uri, Integer port) { loglevel = 0; this.scscpUri = "direct-localhost"; this.scscpPort = 0; computations = new HashMap<String,Computation>(); waitingComputations = new ArrayBlockingQueue<Computation>(16383); this.serviceName = "SPSD"; this.serviceVersion = "1.6-SNAPSHOT"; this.serviceId = "SPSD"; this.scscpVersion = "1.3"; this.workers = new LinkedList(); state = CLIENT_IDLE; resultThread = new Thread(this); resultThread.start(); handlers = new LinkedList<AbstractSPSDHandler>(); handlers.add(new AllPairsHandler()); handlers.add(new MapHandler()); handlers.add(new ZipHandler()); handlers.add(new MapIntervalHandler()); } public void addWorker(SCSCPClient worker) { if (!worker.getServiceName().equals("SPSD")) this.workers.add(worker); } public void addWorkers(Collection<SCSCPClient> workers) { for(SCSCPClient worker : workers) if (!worker.getServiceName().equals("SPSD")) this.workers.add(worker); } public List<SCSCPClient> getWorkers() { return workers; } public void clearWorkers() { workers.clear(); } public boolean removeWorker(SCSCPClient c) { return workers.remove(c); } public int getWorkerCount() { return workers.size(); } @Override public void run() { NotificationCenter.getNC().sendNotification(this, "RUNNING", null); // initialization log(1, " # started waiting-for-result-thread "); // run-loop OpenMathBase result = null; try { while (true) { if (waitingComputations.size() == 0) this.state = CLIENT_IDLE; do { currentComputation = ((ArrayBlockingQueue<Computation>) waitingComputations).poll(1, TimeUnit.SECONDS); } while (null == currentComputation); ProcedureCall pc = currentComputation.getProcedureCall(); boolean handeled = false; for(AbstractSPSDHandler pch : handlers) { if (pc.getServiceName().equals(pch.getServiceName())) { pch.setWorkers(workers); try { result = pch.handlePayload(pc.getPayload()); } catch (OpenMathException e) { result = (new OMSymbol("scscp1", "error_system_specific")).apply( new OpenMathBase[] { new OMString(e.getMessage()) }); } currentComputation.finished(result.toOMObject()); handeled = true; break; } } if (!handeled) { currentComputation.finished(OpenMathBase.parse("scscp1.error_system_specific!('Could not handle "+pc.getServiceName().toPopcorn()+"')")); } NotificationCenter.getNC().sendNotification(this, "ComputationFinished", null); currentComputation = null; } } catch (Exception e) { e.printStackTrace(); } // System.out.println("# SPSD run loop died -- This should not have happened."); NotificationCenter.getNC().sendNotification(this, "DEAD", null); } // run }