[ 
https://issues.apache.org/jira/browse/CRUNCH-486?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Josh Wills resolved CRUNCH-486.
-------------------------------
       Resolution: Fixed
    Fix Version/s: 0.12.0

Pushed to master.

> Join with custom Writable PType registered using Writables.registerComparable 
> NPEs during shuffle
> -------------------------------------------------------------------------------------------------
>
>                 Key: CRUNCH-486
>                 URL: https://issues.apache.org/jira/browse/CRUNCH-486
>             Project: Crunch
>          Issue Type: Bug
>          Components: Core
>    Affects Versions: 0.11.0
>            Reporter: Brandon Vargo
>            Assignee: Josh Wills
>            Priority: Minor
>             Fix For: 0.12.0
>
>         Attachments: CRUNCH-486.patch, CRUNCH-486b.patch
>
>
> When joining two PTables on a key that is a custom writable PType, the 
> shuffler will fail with the following NullPointerException under Hadoop2 if 
> the custom type has been registered using Writables.registerComparable. This 
> happens regardless of whether a specific integer code is provided or the 
> default hashCode()-based value is used.
> {noformat}
> org.apache.hadoop.mapred.YarnChild: Exception running child : 
> org.apache.hadoop.mapreduce.task.reduce.Shuffle$ShuffleError: Error while 
> doing final merge 
>       at org.apache.hadoop.mapreduce.task.reduce.Shuffle.run(Shuffle.java:160)
>       at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:376)
>       at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:168)
>       at java.security.AccessController.doPrivileged(Native Method)
>       at javax.security.auth.Subject.doAs(Subject.java:415)
>       at 
> org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1614)
>       at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:163)
> Caused by: java.lang.NullPointerException
>       at java.lang.Class.isAssignableFrom(Native Method)
>       at 
> org.apache.crunch.types.writable.TupleWritable$Comparator.compareField(TupleWritable.java:317)
>       at 
> org.apache.crunch.types.writable.TupleWritable$Comparator.compare(TupleWritable.java:284)
>       at org.apache.hadoop.mapred.Merger$MergeQueue.lessThan(Merger.java:578)
>       at org.apache.hadoop.util.PriorityQueue.upHeap(PriorityQueue.java:128)
>       at org.apache.hadoop.util.PriorityQueue.put(PriorityQueue.java:55)
>       at org.apache.hadoop.mapred.Merger$MergeQueue.merge(Merger.java:669)
>       at org.apache.hadoop.mapred.Merger.merge(Merger.java:193)
>       at 
> org.apache.hadoop.mapreduce.task.reduce.MergeManagerImpl.finalMerge(MergeManagerImpl.java:804)
>       at 
> org.apache.hadoop.mapreduce.task.reduce.MergeManagerImpl.close(MergeManagerImpl.java:369)
>       at org.apache.hadoop.mapreduce.task.reduce.Shuffle.run(Shuffle.java:158)
>       ... 6 more
> {noformat}
> It appears that the Writables.WRITABLE_CODES entries are not deserialized 
> from the configuration during the shuffle phase of a join until 
> TupleWritable.setConf() is called. However, because TupleWritable.Comparator 
> is registered as a raw comparator for TupleWritable, the shuffler uses the 
> comparator without instantiating or configuring a TupleWritable instance. As 
> a result, the type codes for the custom types are not available when the 
> comparator starts to run.
> HADOOP-10686 made WritableComparator implement Configurable, but this was not 
> released until Hadoop 2.5. If I build Crunch against Hadoop 2.5 and copy 
> TupleWritable's setConf() function to TupleWritable.Comparator, then the 
> shuffle works as expected. However, since Crunch currently targets Hadoop 
> 2.2, this does not work for the current version of Crunch.
> As as a workaround, it appears that if the 
> {{mapreduce.job.output.key.comparator.class}} property is set in the 
> configuration, then the instance is created in 
> JobConf.getOutputKeyComparator() using ReflectionUtils instead of using the 
> WritableComparator registration. ReflectionUtils will pass the configuration 
> to anything that implements Configurable, so setting 
> {{mapreduce.job.output.key.comparator.class}} to TupleWritable.Comparator and 
> implementing Configurable might work for Hadoop versions older than 2.5. I 
> have yet to try this, though, and I have not looked into Hadoop1 to see if 
> this would also work there.
> If the shuffle is able to register the type codes via either method above, 
> then there is one small secondary issue that I hit: 
> Writables.registerComparable checks if the type code is already present in 
> the map; if the type code is already in use, then it throws an exception, 
> even if the class being registered is the same as the existing class. With 
> the type codes being initialized during the shuffle phase, any later call to 
> registerComparable for the same type code and class will fail. I currently 
> have my registerComparable call in a static initialization block for my 
> PType, so it is called whenever my writable type is first used under Crunch; 
> in this case, it happens when the reduce phase starts. Checking to see if the 
> class being registered and the existing class are equal inside of 
> registerComparable before throwing an error, similar to the one that is in 
> Guava's AbstractBiMap, prevents this exception from being thrown.
> The above was happening using 0.11.0-hadoop2 on Hadoop 2.5.0 (CDH 5.2). The 
> modifications I mention above were made on top of {{d4f23c4}} and also tested 
> on CDH 5.2.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to