/** * Licensed to Ravel, Inc. under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. Ravel, Inc. licenses this file * to you 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.goldenorb; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.ipc.RPC; import org.apache.hadoop.net.DNS; import org.goldenorb.conf.OrbConfigurable; import org.goldenorb.conf.OrbConfiguration; import org.goldenorb.jet.OrbPartitionMember; import org.goldenorb.jet.PartitionRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * {@link OrbPartitionManager} launches partitions via the proxy object {@link PartitionProcess}. It * communicates with {@link OrbPartitionMember} processes via Hadoop RPC. * * @param <M> The class of {@link PartitionProcess} that will be launched by {@link OrbPartitionManager} */ public class OrbPartitionManager<M extends PartitionProcess> implements OrbConfigurable { private final Logger logger = LoggerFactory.getLogger(OrbPartitionManager.class); private Map<String,List<M>> processesByJob = new HashMap<String,List<M>>(); private Class<M> processClass; private OrbConfiguration conf; private String ipAddress; // RPC client to be used for soft-killing OrbPartition processes private OrbPartitionManagerProtocol partitionClient; /** * Constructor * * @param OrbConfiguration conf * @param Class<M> clazz */ public OrbPartitionManager(OrbConfiguration conf, Class<M> clazz) { this.conf = conf; this.processClass = clazz; try { ipAddress = DNS.getDefaultHost(this.conf.getOrbLauncherNetworkDevice()); if (ipAddress.endsWith(".")) { ipAddress = ipAddress.substring(0, ipAddress.length() - 1); } logger.debug("setting ipAddress to " + ipAddress); } catch (UnknownHostException e) { logger.error(e.getMessage()); } } /** * * @param int requested * @param int reserved * @param int basePartitionID */ // public void launchPartitions(int requested, int reserved, int basePartitionID, String jobNumber) throws InstantiationException, IllegalAccessException { public void launchPartitions(PartitionRequest request) throws InstantiationException, IllegalAccessException { int requested = request.getActivePartitions(); int reserved = request.getReservedPartitions(); logger.info("requested " + requested + ", reserved " + reserved); List<M> processes = new ArrayList<M>(); for (int i = 0; i < (requested + reserved); i++) { M partitionProcess = processClass.newInstance(); partitionProcess.setConf(conf); partitionProcess.setCurrentJobConf(request.getJobConf()); partitionProcess.setJobNumber(request.getJobID()); partitionProcess.setProcessNum(i); if (i < requested) { partitionProcess.setPartitionID(request.getBasePartitionID() + i); } else { partitionProcess.setReserved(true); partitionProcess.setPartitionID(-1); } OutputStream outStream = null; OutputStream errStream = null; try { outStream = System.out; //new FileOutputStream(new File(ipAddress + Integer.toString(3000 + partition.getPartitionID()) + ".out")); errStream = System.err; //new FileOutputStream(new File(ipAddress + Integer.toString(3000 + partition.getPartitionID()) + ".err")); } catch (Exception e) { logger.error(e.getMessage()); } logger.debug("launching partition process " + partitionProcess.getPartitionID() + " on " + ipAddress); partitionProcess.launch(outStream, errStream); processes.add(partitionProcess); } processesByJob.put(request.getJobID(), processes); } /** * */ public void stop(String jobNumber) { Configuration rpcConf = new Configuration(); if (processesByJob.containsKey(jobNumber)) { for (M p : processesByJob.get(jobNumber)) { int rpcPort = conf.getOrbPartitionManagementBaseport() + p.getProcessNum() + 100; InetSocketAddress addr = new InetSocketAddress(ipAddress, rpcPort); try { partitionClient = (OrbPartitionManagerProtocol) RPC.waitForProxy(OrbPartitionManagerProtocol.class, OrbPartitionManagerProtocol.versionID, addr, rpcConf); int partitionStatus = partitionClient.stop(); if (partitionStatus > 0) { // wait some time before trying to stop it again wait(5000); if (partitionClient.isRunning()) { p.kill(); } } else if (partitionStatus < 0) { p.kill(); } } catch (IOException e) { logger.error(e.getMessage()); } catch (InterruptedException e) { logger.error(e.getMessage()); } } } } /** * */ public void kill(String jobNumber) { if (processesByJob.containsKey(jobNumber)) { for (M p : processesByJob.get(jobNumber)) { p.kill(); } } } /** * Set the orbConf * @param OrbConfiguration orbConf */ @Override public void setOrbConf(OrbConfiguration orbConf) { this.conf = orbConf; } /** * Return the orbConf */ @Override public OrbConfiguration getOrbConf() { return conf; } /** * Return the childProcesses */ public Map<String,List<M>> getProcessesByJob() { return processesByJob; } /** * Return the ipAddress */ public String getIpAddress() { return ipAddress; } /** * Set the partitionProcessClass * @param Class<M> partitionProcessClass */ public void setPartitionProcessClass(Class<M> partitionProcessClass) { this.processClass = partitionProcessClass; } /** * Return the partitionProcessClass */ public Class<M> getPartitionProcessClass() { return processClass; } }