in src/org/apache/pig/backend/hadoop/executionengine/Launcher.java [361:566]
private Throwable getExceptionFromStrings(String[] stackTraceLines,
int startingLineNum) throws Exception {
/*
* parse the array of string and throw the appropriate exception first:
* from the line startingLineNum extract the exception name extract the
* message if any fourth: create the appropriate exception and return it
* An example of the stack trace:
* org.apache.pig.backend.executionengine.ExecException: ERROR 1075:
* Received a bytearray from the UDF. Cannot determine how to convert
* the bytearray to int. at
* org.apache.pig.backend.hadoop.executionengine
* .physicalLayer.expressionOperators.POCast.getNext(POCast.java:152) at
* org.apache.pig.backend.hadoop.executionengine.physicalLayer.
* expressionOperators.LessThanExpr.getNext(LessThanExpr.java:85) at
* org.apache.pig.backend.hadoop.executionengine.physicalLayer.
* relationalOperators.POFilter.getNext(POFilter.java:148) at
* org.apache.
* pig.backend.hadoop.executionengine.mapReduceLayer.PigMapBase
* .runPipeline(PigMapBase.java:184) at
* org.apache.pig.backend.hadoop.executionengine
* .mapReduceLayer.PigMapBase.map(PigMapBase.java:174) at
* org.apache.pig.
* backend.hadoop.executionengine.mapReduceLayer.PigMapOnly$Map
* .map(PigMapOnly.java:65) at
* org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:47) at
* org.apache.hadoop.mapred.MapTask.run(MapTask.java:227) at
* org.apache.hadoop
* .mapred.TaskTracker$Child.main(TaskTracker.java:2207)
*/
if (stackTraceLines.length > 0
&& startingLineNum < (stackTraceLines.length - 1)) {
// the regex for matching the exception class name; note the use of
// the $ for matching nested classes
String exceptionNameDelimiter = "(\\w+(\\$\\w+)?\\.)+\\w+";
Pattern exceptionNamePattern = Pattern
.compile(exceptionNameDelimiter);
// from the first line extract the exception name and the exception
// message
Matcher exceptionNameMatcher = exceptionNamePattern
.matcher(stackTraceLines[startingLineNum]);
String exceptionName = null;
String exceptionMessage = null;
if (exceptionNameMatcher.find()) {
exceptionName = exceptionNameMatcher.group();
/*
* note that the substring is from end + 2 the regex matcher
* ends at one position beyond the match in this case it will
* end at colon (:) the exception message will have a preceding
* space (after the colon (:))
*/
if (exceptionName.contains(OOM_ERR)) {
outOfMemory = true;
}
if (stackTraceLines[startingLineNum].length() > exceptionNameMatcher
.end()) {
exceptionMessage = stackTraceLines[startingLineNum]
.substring(exceptionNameMatcher.end() + 2);
}
++startingLineNum;
}
// the exceptionName should not be null
if (exceptionName != null) {
ArrayList<StackTraceElement> stackTraceElements = Lists.newArrayList();
// Create stack trace elements for the remaining lines
String stackElementRegex = "\\s+at\\s+(\\w+(\\$\\w+)?\\.)+(\\<)?\\w+(\\>)?";
Pattern stackElementPattern = Pattern
.compile(stackElementRegex);
String pigExceptionRegex = "org\\.apache\\.pig\\.";
Pattern pigExceptionPattern = Pattern
.compile(pigExceptionRegex);
String moreElementRegex = "\\s+\\.\\.\\.\\s+\\d+\\s+more";
Pattern moreElementPattern = Pattern.compile(moreElementRegex);
int lineNum = startingLineNum;
for (; lineNum < (stackTraceLines.length - 1); ++lineNum) {
Matcher stackElementMatcher = stackElementPattern
.matcher(stackTraceLines[lineNum]);
if (stackElementMatcher.find()) {
StackTraceElement ste = getStackTraceElement(stackTraceLines[lineNum]);
stackTraceElements.add(ste);
String className = ste.getClassName();
Matcher pigExceptionMatcher = pigExceptionPattern
.matcher(className);
if (pigExceptionMatcher.find()) {
pigException = true;
}
} else {
Matcher moreElementMatcher = moreElementPattern
.matcher(stackTraceLines[lineNum]);
if (moreElementMatcher.find()) {
++lineNum;
}
break;
}
}
startingLineNum = lineNum;
// create the appropriate exception; setup the stack trace and
// message
Object object = PigContext
.instantiateFuncFromSpec(exceptionName);
if (object instanceof PigException) {
// extract the error code and message the regex for matching
// the custom format of ERROR <ERROR CODE>:
String errMessageRegex = "ERROR\\s+\\d+:";
Pattern errMessagePattern = Pattern
.compile(errMessageRegex);
Matcher errMessageMatcher = errMessagePattern
.matcher(exceptionMessage);
if (errMessageMatcher.find()) {
String errMessageStub = errMessageMatcher.group();
/*
* extract the actual exception message sans the ERROR
* <ERROR CODE>: again note that the matcher ends at the
* space following the colon (:) the exception message
* appears after the space and hence the end + 1
*/
exceptionMessage = exceptionMessage
.substring(errMessageMatcher.end() + 1);
// the regex to match the error code wich is a string of
// numerals
String errCodeRegex = "\\d+";
Pattern errCodePattern = Pattern.compile(errCodeRegex);
Matcher errCodeMatcher = errCodePattern
.matcher(errMessageStub);
String code = null;
if (errCodeMatcher.find()) {
code = errCodeMatcher.group();
}
// could receive a number format exception here but it
// will be propagated up the stack
int errCode;
if (code != null)
errCode = Integer.parseInt(code);
else
errCode = 2998;
// create the exception with the message and then set
// the error code and error source
FuncSpec funcSpec = new FuncSpec(exceptionName,
exceptionMessage);
object = PigContext.instantiateFuncFromSpec(funcSpec);
((PigException) object).setErrorCode(errCode);
((PigException) object).setErrorSource(PigException
.determineErrorSource(errCode));
} else { // else for if(errMessageMatcher.find())
/*
* did not find the error code which means that the
* PigException or its subclass is not returning the
* error code highly unlikely: should never be here
*/
FuncSpec funcSpec = new FuncSpec(exceptionName,
exceptionMessage);
object = PigContext.instantiateFuncFromSpec(funcSpec);
((PigException) object).setErrorCode(2997);// generic
// error
// code
((PigException) object)
.setErrorSource(PigException.BUG);
}
} else { // else for if(object instanceof PigException)
// its not PigException; create the exception with the
// message
object = PigContext.instantiateFuncFromSpec(new FuncSpec(
exceptionName, exceptionMessage));
}
StackTraceElement[] steArr = new StackTraceElement[stackTraceElements
.size()];
((Throwable) object).setStackTrace(stackTraceElements
.toArray(steArr));
if (startingLineNum < (stackTraceLines.length - 1)) {
Throwable e = getExceptionFromStrings(stackTraceLines,
startingLineNum);
((Throwable) object).initCause(e);
}
return (Throwable) object;
} else { // else for if(exceptionName != null)
int errCode = 2055;
String msg = "Did not find exception name to create exception from string: "
+ Arrays.toString(stackTraceLines);
throw new ExecException(msg, errCode, PigException.BUG);
}
} else { // else for if(lines.length > 0)
int errCode = 2056;
String msg = "Cannot create exception from empty string.";
throw new ExecException(msg, errCode, PigException.BUG);
}
}