PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/core/src/main/java/org/apache/hama/bsp/BSPPeerImpl.java

#
Java | 436 lines | 297 code | 64 blank | 75 comment | 29 complexity | 149c9a1e31464679c171aae5b58317b4 MD5 | raw file
Possible License(s): Apache-2.0, CPL-1.0
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package org.apache.hama.bsp;
  19. import java.io.IOException;
  20. import java.net.InetSocketAddress;
  21. import java.util.Iterator;
  22. import java.util.LinkedList;
  23. import java.util.Map.Entry;
  24. import org.apache.commons.logging.Log;
  25. import org.apache.commons.logging.LogFactory;
  26. import org.apache.hadoop.conf.Configuration;
  27. import org.apache.hadoop.fs.FSDataOutputStream;
  28. import org.apache.hadoop.fs.FileSystem;
  29. import org.apache.hadoop.fs.Path;
  30. import org.apache.hadoop.io.BytesWritable;
  31. import org.apache.hadoop.io.DataInputBuffer;
  32. import org.apache.hadoop.util.ReflectionUtils;
  33. import org.apache.hama.Constants;
  34. import org.apache.hama.bsp.Counters.Counter;
  35. import org.apache.hama.bsp.message.MessageManager;
  36. import org.apache.hama.bsp.message.MessageManagerFactory;
  37. import org.apache.hama.bsp.sync.SyncClient;
  38. import org.apache.hama.bsp.sync.SyncException;
  39. import org.apache.hama.bsp.sync.SyncServiceFactory;
  40. import org.apache.hama.ipc.BSPPeerProtocol;
  41. import org.apache.hama.util.KeyValuePair;
  42. /**
  43. * This class represents a BSP peer.
  44. */
  45. public class BSPPeerImpl<KEYIN, VALUEIN, KEYOUT, VALUEOUT> implements
  46. BSPPeer<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {
  47. private static final Log LOG = LogFactory.getLog(BSPPeerImpl.class);
  48. protected static enum PeerCounter {
  49. SUPERSTEPS
  50. }
  51. private final Configuration conf;
  52. private final FileSystem fs;
  53. private BSPJob bspJob;
  54. private TaskStatus currentTaskStatus;
  55. private TaskAttemptID taskId;
  56. private BSPPeerProtocol umbilical;
  57. private String[] allPeers;
  58. // SYNC
  59. private SyncClient syncClient;
  60. private MessageManager messenger;
  61. // IO
  62. private int partition;
  63. private String splitClass;
  64. private BytesWritable split;
  65. private OutputCollector<KEYOUT, VALUEOUT> collector;
  66. private RecordReader<KEYIN, VALUEIN> in;
  67. private RecordWriter<KEYOUT, VALUEOUT> outWriter;
  68. private InetSocketAddress peerAddress;
  69. private Counters counters;
  70. /**
  71. * Protected default constructor for LocalBSPRunner.
  72. */
  73. protected BSPPeerImpl() {
  74. conf = null;
  75. fs = null;
  76. }
  77. /**
  78. * For unit test.
  79. *
  80. * @param conf is the configuration file.
  81. * @param dfs is the Hadoop FileSystem.
  82. */
  83. protected BSPPeerImpl(final Configuration conf, FileSystem dfs) {
  84. this.conf = conf;
  85. this.fs = dfs;
  86. }
  87. /**
  88. * BSPPeer Constructor.
  89. *
  90. * BSPPeer acts on behalf of clients performing bsp() tasks.
  91. *
  92. * @param conf is the configuration file containing bsp peer host, port, etc.
  93. * @param umbilical is the bsp protocol used to contact its parent process.
  94. * @param taskId is the id that current process holds.
  95. * @throws Exception
  96. */
  97. public BSPPeerImpl(BSPJob job, Configuration conf, TaskAttemptID taskId,
  98. BSPPeerProtocol umbilical, int partition, String splitClass,
  99. BytesWritable split, Counters counters) throws Exception {
  100. this.conf = conf;
  101. this.taskId = taskId;
  102. this.umbilical = umbilical;
  103. this.bspJob = job;
  104. // IO
  105. this.partition = partition;
  106. this.splitClass = splitClass;
  107. this.split = split;
  108. this.counters = counters;
  109. this.fs = FileSystem.get(conf);
  110. String bindAddress = conf.get(Constants.PEER_HOST,
  111. Constants.DEFAULT_PEER_HOST);
  112. int bindPort = conf
  113. .getInt(Constants.PEER_PORT, Constants.DEFAULT_PEER_PORT);
  114. peerAddress = new InetSocketAddress(bindAddress, bindPort);
  115. initialize();
  116. syncClient.register(taskId.getJobID(), taskId, peerAddress.getHostName(),
  117. peerAddress.getPort());
  118. // initial barrier syncing to get all the hosts to the same point, to get
  119. // consistent peernames.
  120. syncClient.enterBarrier(taskId.getJobID(), taskId, -1);
  121. syncClient.leaveBarrier(taskId.getJobID(), taskId, -1);
  122. setCurrentTaskStatus(new TaskStatus(taskId.getJobID(), taskId, 0,
  123. TaskStatus.State.RUNNING, "running", peerAddress.getHostName(),
  124. TaskStatus.Phase.STARTING, counters));
  125. messenger = MessageManagerFactory.getMessageManager(conf);
  126. messenger.init(conf, peerAddress);
  127. }
  128. @SuppressWarnings("unchecked")
  129. public void initialize() throws Exception {
  130. syncClient = SyncServiceFactory.getSyncClient(conf);
  131. syncClient.init(conf, taskId.getJobID(), taskId);
  132. initInput();
  133. // just output something when the user configured it
  134. if (conf.get("bsp.output.dir") != null) {
  135. Path outdir = new Path(conf.get("bsp.output.dir"), Task
  136. .getOutputName(partition));
  137. outWriter = bspJob.getOutputFormat().getRecordWriter(fs, bspJob,
  138. outdir.makeQualified(fs).toString());
  139. final RecordWriter<KEYOUT, VALUEOUT> finalOut = outWriter;
  140. collector = new OutputCollector<KEYOUT, VALUEOUT>() {
  141. public void collect(KEYOUT key, VALUEOUT value) throws IOException {
  142. finalOut.write(key, value);
  143. }
  144. };
  145. }
  146. }
  147. @SuppressWarnings("unchecked")
  148. public void initInput() throws IOException {
  149. // just read input if the user defined one
  150. if (conf.get("bsp.input.dir") != null) {
  151. InputSplit inputSplit = null;
  152. // reinstantiate the split
  153. try {
  154. inputSplit = (InputSplit) ReflectionUtils.newInstance(
  155. getConfiguration().getClassByName(splitClass), getConfiguration());
  156. } catch (ClassNotFoundException exp) {
  157. IOException wrap = new IOException("Split class " + splitClass
  158. + " not found");
  159. wrap.initCause(exp);
  160. throw wrap;
  161. }
  162. DataInputBuffer splitBuffer = new DataInputBuffer();
  163. splitBuffer.reset(split.getBytes(), 0, split.getLength());
  164. inputSplit.readFields(splitBuffer);
  165. if (in != null) {
  166. in.close();
  167. }
  168. in = bspJob.getInputFormat().getRecordReader(inputSplit, bspJob);
  169. }
  170. }
  171. @Override
  172. public BSPMessage getCurrentMessage() throws IOException {
  173. return messenger.getCurrentMessage();
  174. }
  175. @Override
  176. public void send(String peerName, BSPMessage msg) throws IOException {
  177. messenger.send(peerName, msg);
  178. }
  179. private String checkpointedPath() {
  180. String backup = conf.get("bsp.checkpoint.prefix_path", "/checkpoint/");
  181. String ckptPath = backup + bspJob.getJobID().toString() + "/"
  182. + getSuperstepCount() + "/" + this.taskId.toString();
  183. if (LOG.isDebugEnabled())
  184. LOG.debug("Messages are to be saved to " + ckptPath);
  185. return ckptPath;
  186. }
  187. void checkpoint(String checkpointedPath, BSPMessageBundle bundle) {
  188. FSDataOutputStream out = null;
  189. try {
  190. out = this.fs.create(new Path(checkpointedPath));
  191. bundle.write(out);
  192. } catch (IOException ioe) {
  193. LOG.warn("Fail checkpointing messages to " + checkpointedPath, ioe);
  194. } finally {
  195. try {
  196. if (null != out)
  197. out.close();
  198. } catch (IOException e) {
  199. LOG.warn("Fail to close dfs output stream while checkpointing.", e);
  200. }
  201. }
  202. }
  203. /*
  204. * (non-Javadoc)
  205. * @see org.apache.hama.bsp.BSPPeerInterface#sync()
  206. */
  207. @Override
  208. public void sync() throws IOException, SyncException, InterruptedException {
  209. enterBarrier();
  210. Iterator<Entry<InetSocketAddress, LinkedList<BSPMessage>>> it = messenger
  211. .getMessageIterator();
  212. while (it.hasNext()) {
  213. Entry<InetSocketAddress, LinkedList<BSPMessage>> entry = it.next();
  214. final InetSocketAddress addr = entry.getKey();
  215. final Iterable<BSPMessage> messages = entry.getValue();
  216. final BSPMessageBundle bundle = combineMessages(messages);
  217. if (conf.getBoolean("bsp.checkpoint.enabled", false)) {
  218. checkpoint(checkpointedPath(), bundle);
  219. }
  220. // remove this message during runtime to save a bit of memory
  221. it.remove();
  222. messenger.transfer(addr, bundle);
  223. }
  224. leaveBarrier();
  225. incrCounter(PeerCounter.SUPERSTEPS, 1);
  226. currentTaskStatus.setCounters(counters);
  227. umbilical.statusUpdate(taskId, currentTaskStatus);
  228. // Clear outgoing queues.
  229. messenger.clearOutgoingQueues();
  230. }
  231. private BSPMessageBundle combineMessages(Iterable<BSPMessage> messages) {
  232. if (!conf.getClass("bsp.combiner.class", Combiner.class).equals(
  233. Combiner.class)) {
  234. Combiner combiner = (Combiner) ReflectionUtils.newInstance(conf.getClass(
  235. "bsp.combiner.class", Combiner.class), conf);
  236. return combiner.combine(messages);
  237. } else {
  238. BSPMessageBundle bundle = new BSPMessageBundle();
  239. for (BSPMessage message : messages) {
  240. bundle.addMessage(message);
  241. }
  242. return bundle;
  243. }
  244. }
  245. protected void enterBarrier() throws SyncException {
  246. syncClient.enterBarrier(taskId.getJobID(), taskId, currentTaskStatus
  247. .getSuperstepCount());
  248. }
  249. protected void leaveBarrier() throws SyncException {
  250. syncClient.leaveBarrier(taskId.getJobID(), taskId, currentTaskStatus
  251. .getSuperstepCount());
  252. }
  253. public void close() throws SyncException, IOException, InterruptedException {
  254. if (in != null) {
  255. in.close();
  256. }
  257. if (outWriter != null) {
  258. outWriter.close();
  259. }
  260. this.clear();
  261. syncClient.close();
  262. messenger.close();
  263. }
  264. @Override
  265. public void clear() {
  266. messenger.clearOutgoingQueues();
  267. }
  268. /**
  269. * @return the string as host:port of this Peer
  270. */
  271. public String getPeerName() {
  272. return peerAddress.getHostName() + ":" + peerAddress.getPort();
  273. }
  274. @Override
  275. public String[] getAllPeerNames() {
  276. initPeerNames();
  277. return allPeers;
  278. }
  279. @Override
  280. public String getPeerName(int index) {
  281. initPeerNames();
  282. return allPeers[index];
  283. }
  284. @Override
  285. public int getNumPeers() {
  286. initPeerNames();
  287. return allPeers.length;
  288. }
  289. private void initPeerNames() {
  290. if (allPeers == null) {
  291. allPeers = syncClient.getAllPeerNames(taskId);
  292. }
  293. }
  294. /**
  295. * @return the number of messages
  296. */
  297. @Override
  298. public int getNumCurrentMessages() {
  299. return messenger.getNumCurrentMessages();
  300. }
  301. /**
  302. * Sets the current status
  303. *
  304. * @param currentTaskStatus
  305. */
  306. public void setCurrentTaskStatus(TaskStatus currentTaskStatus) {
  307. this.currentTaskStatus = currentTaskStatus;
  308. }
  309. /**
  310. * @return the count of current super-step
  311. */
  312. public long getSuperstepCount() {
  313. return currentTaskStatus.getSuperstepCount();
  314. }
  315. /**
  316. * Gets the job configuration.
  317. *
  318. * @return the conf
  319. */
  320. public Configuration getConfiguration() {
  321. return conf;
  322. }
  323. /*
  324. * IO STUFF
  325. */
  326. @Override
  327. public void write(KEYOUT key, VALUEOUT value) throws IOException {
  328. collector.collect(key, value);
  329. }
  330. @Override
  331. public boolean readNext(KEYIN key, VALUEIN value) throws IOException {
  332. return in.next(key, value);
  333. }
  334. @Override
  335. public KeyValuePair<KEYIN, VALUEIN> readNext() throws IOException {
  336. KEYIN k = in.createKey();
  337. VALUEIN v = in.createValue();
  338. if (in.next(k, v)) {
  339. return new KeyValuePair<KEYIN, VALUEIN>(k, v);
  340. } else {
  341. return null;
  342. }
  343. }
  344. @Override
  345. public void reopenInput() throws IOException {
  346. initInput();
  347. }
  348. @Override
  349. public Counter getCounter(Enum<?> name) {
  350. return counters == null ? null : counters.findCounter(name);
  351. }
  352. @Override
  353. public Counter getCounter(String group, String name) {
  354. Counters.Counter counter = null;
  355. if (counters != null) {
  356. counter = counters.findCounter(group, name);
  357. }
  358. return counter;
  359. }
  360. @Override
  361. public void incrCounter(Enum<?> key, long amount) {
  362. if (counters != null) {
  363. counters.incrCounter(key, amount);
  364. }
  365. }
  366. @Override
  367. public void incrCounter(String group, String counter, long amount) {
  368. if (counters != null) {
  369. counters.incrCounter(group, counter, amount);
  370. }
  371. }
  372. }