001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.reef.runtime.common.launch; 020 021import com.google.protobuf.ByteString; 022import org.apache.reef.proto.ReefServiceProtos; 023import org.apache.reef.runtime.common.launch.parameters.ErrorHandlerRID; 024import org.apache.reef.runtime.common.launch.parameters.LaunchID; 025import org.apache.reef.runtime.common.utils.ExceptionCodec; 026import org.apache.reef.runtime.common.utils.RemoteManager; 027import org.apache.reef.tang.InjectionFuture; 028import org.apache.reef.tang.annotations.Parameter; 029import org.apache.reef.wake.EventHandler; 030 031import javax.inject.Inject; 032import java.util.logging.Level; 033import java.util.logging.Logger; 034 035 036/** 037 * The error handler REEF registers with Wake. 038 */ 039public final class REEFErrorHandler implements EventHandler<Throwable> { 040 041 private static final Logger LOG = Logger.getLogger(REEFErrorHandler.class.getName()); 042 043 // This class is used as the ErrorHandler in the RemoteManager. Hence, we need an InjectionFuture here. 044 private final InjectionFuture<RemoteManager> remoteManager; 045 private final String launchID; 046 private final String errorHandlerRID; 047 private final ExceptionCodec exceptionCodec; 048 049 @Inject 050 REEFErrorHandler(final InjectionFuture<RemoteManager> remoteManager, 051 final @Parameter(ErrorHandlerRID.class) String errorHandlerRID, 052 final @Parameter(LaunchID.class) String launchID, 053 final ExceptionCodec exceptionCodec) { 054 this.errorHandlerRID = errorHandlerRID; 055 this.remoteManager = remoteManager; 056 this.launchID = launchID; 057 this.exceptionCodec = exceptionCodec; 058 } 059 060 @Override 061 public void onNext(final Throwable e) { 062 LOG.log(Level.SEVERE, "Uncaught exception.", e); 063 // TODO: This gets a new EventHandler each time an exception is caught. It would be better to cache the handler. But 064 // that introduces threading issues and isn't really worth it, as the JVM typically will be killed once we catch an 065 // Exception in here. 066 if (!this.errorHandlerRID.equals(ErrorHandlerRID.NONE)) { 067 final EventHandler<ReefServiceProtos.RuntimeErrorProto> runtimeErrorHandler = this.remoteManager.get() 068 .getHandler(errorHandlerRID, ReefServiceProtos.RuntimeErrorProto.class); 069 final ReefServiceProtos.RuntimeErrorProto message = ReefServiceProtos.RuntimeErrorProto.newBuilder() 070 .setName("reef") 071 .setIdentifier(launchID) 072 .setMessage(e.getMessage()) 073 .setException(ByteString.copyFrom(this.exceptionCodec.toBytes(e))) 074 .build(); 075 try { 076 runtimeErrorHandler.onNext(message); 077 } catch (final Throwable t) { 078 LOG.log(Level.SEVERE, "Unable to send the error upstream", t); 079 } 080 } else { 081 LOG.log(Level.SEVERE, "Caught an exception from Wake we cannot send upstream because there is no upstream"); 082 } 083 } 084 085 public void close() { 086 try { 087 this.remoteManager.get().close(); 088 } catch (final Throwable ex) { 089 LOG.log(Level.SEVERE, "Unable to close the remote manager", ex); 090 } 091 } 092 093 @Override 094 public String toString() { 095 return "REEFErrorHandler{" + 096 "remoteManager=" + remoteManager + 097 ", launchID='" + launchID + '\'' + 098 ", errorHandlerRID='" + errorHandlerRID + '\'' + 099 '}'; 100 } 101}