title: How can I use MarkableIterator in Hadoop?
body: <p><strong>Background:</strong><br/>
  <code>MarkableIteratorInterface</code> is an interface for an iterator that supports mark-reset functionality. Basically, you can iterate over the Reducer's values multiple times my "marking" a position and "resetting" back to it. The data is temporarily cached to memory (and then to disk when memory becomes full).</p>
  
  <p>This is possible if the <code>Reducer</code>'s <code>ValueIterator</code> implements <code>MarkableIteratorInterface</code> - that depends upon the Hadoop implementation. <a href="http://hadoop.apache.org/docs/current/api/org/apache/hadoop/mapreduce/MarkableIterator.html" rel="nofollow"><code>MarkableIterator</code></a> is a wrapper that's used by the client reducer code to iterate (and reiterate) over the values.</p>
  
  <p>Here's the JIRA issue about the feature: <a href="https://issues.apache.org/jira/browse/HADOOP-5266" rel="nofollow">https://issues.apache.org/jira/browse/HADOOP-5266</a>.</p>
  
  <p><strong>Problem:</strong><br/>
  I cannot find a way to use this functionality. The only mention of the actual code I found is on a <a href="https://svn.apache.org/repos/asf/hadoop/common/branches/pre-HADOOP-4687/src/mapred/org/apache/hadoop/mapreduce/ReduceContext.java" rel="nofollow">branch on Apache's svn</a>. I cannot seem to find a single version of a Hadoop distribution, be it from Cloudera or just vanilla Hadoop, that allows this. I've been checking on grepcode for a while. Every task fails with the error: <code>java.lang.IllegalArgumentException: Input Iterator not markable</code>.</p>
  
  <p>Is the only way around this to manually patch the source code and re-compile? Any clues?</p>
  
  <p><strong>Something interesting:</strong></p>
  
  <ul>
  <li>Doing a <code>grep -R 'implements MarkableIteratorInterface' src/.</code> in the
  hadoop tarball's root (scroll below to see version details) does NOT
  reveal a <code>ValueIterator</code> that implements <code>MarkableIteratorInterface</code>,
  as is already evident from grepcode.com</li>
  <li>Also, in <a href="http://archive.cloudera.com/cdh4/cdh/4/hadoop/hadoop/common/CHANGES.txt" rel="nofollow">http://archive.cloudera.com/cdh4/cdh/4/hadoop/hadoop/common/CHANGES.txt</a> and <a href="http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/CHANGES.txt" rel="nofollow">http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/CHANGES.txt</a> if you search for "HADOOP-5266", you'll find the entry under NEW FEATURES for Release 0.21.0 - 2010-08-13. What does this even mean? I'll have to download that release from somewhere and I cannot use any cloudera distribution? But that wouldn't have lots of new features from Hadoop 2.0.0 (like being able to use <code>CompositeInputFormat</code> from the new MR API for example).</li>
  </ul>
  
  <p><strong>pom.xml contents:</strong><br/></p>
  
  <pre><code>&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
      &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
  
      &lt;groupId&gt;com.nileshc&lt;/groupId&gt;
      ...
      ...
      &lt;name&gt;blah&lt;/name&gt;
      &lt;url&gt;http://maven.apache.org&lt;/url&gt;
  
      &lt;properties&gt;
          &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
      &lt;/properties&gt;
  
      &lt;build&gt;
          &lt;plugins&gt;
              &lt;plugin&gt;
                  &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                  &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
                  &lt;version&gt;2.16&lt;/version&gt;
                  &lt;configuration&gt;
                      &lt;skipTests&gt;true&lt;/skipTests&gt;
                  &lt;/configuration&gt;
              &lt;/plugin&gt;
              &lt;plugin&gt;
                  &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                  &lt;artifactId&gt;maven-shade-plugin&lt;/artifactId&gt;
                  &lt;version&gt;1.2.2&lt;/version&gt;
                  &lt;executions&gt;
                      &lt;execution&gt;
                          &lt;phase&gt;package&lt;/phase&gt;
                          &lt;goals&gt;
                              &lt;goal&gt;shade&lt;/goal&gt;
                          &lt;/goals&gt;
                      &lt;/execution&gt;
                  &lt;/executions&gt;
              &lt;/plugin&gt;
          &lt;/plugins&gt;
      &lt;/build&gt;
  
      &lt;repositories&gt;
          &lt;repository&gt;
              &lt;id&gt;cloudera&lt;/id&gt;
              &lt;url&gt;https://repository.cloudera.com/artifactory/cloudera-repos/&lt;/url&gt;
          &lt;/repository&gt;
      &lt;/repositories&gt;
  
      &lt;dependencies&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.apache.hadoop&lt;/groupId&gt;
              &lt;artifactId&gt;hadoop-mapreduce-client-core&lt;/artifactId&gt;
              &lt;version&gt;2.0.0-cdh4.5.0&lt;/version&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.apache.hadoop&lt;/groupId&gt;
              &lt;artifactId&gt;hadoop-client&lt;/artifactId&gt;
              &lt;version&gt;2.0.0-mr1-cdh4.5.0&lt;/version&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.apache.hadoop&lt;/groupId&gt;
              &lt;artifactId&gt;hadoop-core&lt;/artifactId&gt;
              &lt;version&gt;2.0.0-mr1-cdh4.5.0&lt;/version&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;junit&lt;/groupId&gt;
              &lt;artifactId&gt;junit&lt;/artifactId&gt;
              &lt;version&gt;4.10&lt;/version&gt;
              &lt;scope&gt;test&lt;/scope&gt;
              &lt;type&gt;jar&lt;/type&gt;
          &lt;/dependency&gt;
      &lt;/dependencies&gt;
  &lt;/project&gt;
  </code></pre>
  
  <p><strong>Reducer reduce method code:</strong>
  @Override</p>
  
  <pre><code>protected void reduce(LongWritable key, Iterable&lt;CustomWritable&gt; values, Context context) throws IOException, InterruptedException {
      MarkableIterator&lt;CustomWritable&gt; itr = new MarkableIterator&lt;CustomWritable&gt;(values.iterator());
      //Error caused in line above
      itr.mark();
  
      // Compute something
      while (itr.hasNext()) {
          // blah blah...
      }
  </code></pre>
  
  <p>}</p>
  
  <p><strong>Stack trace:</strong></p>
  
  <pre><code>SLF4J: Class path contains multiple SLF4J bindings.
  SLF4J: Found binding in [jar:file:/hadoop2/share/hadoop/mapreduce1/lib/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
  SLF4J: Found binding in [jar:file:/hadoop2/share/hadoop/common/lib/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
  SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
  14/01/31 00:29:35 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
  14/01/31 00:29:39 WARN mapred.JobClient: Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same.
  14/01/31 00:29:39 INFO input.FileInputFormat: Total input paths to process : 2
  14/01/31 00:29:40 INFO mapred.JobClient: Running job: job_201401302213_0004
  14/01/31 00:29:42 INFO mapred.JobClient:  map 0% reduce 0%
  14/01/31 00:30:02 INFO mapred.JobClient:  map 50% reduce 0%
  14/01/31 00:30:25 INFO mapred.JobClient:  map 100% reduce 0%
  14/01/31 00:31:29 INFO mapred.JobClient:  map 100% reduce 33%
  14/01/31 00:31:32 INFO mapred.JobClient:  map 100% reduce 50%
  14/01/31 00:31:33 INFO mapred.JobClient:  map 100% reduce 83%
  14/01/31 00:31:53 INFO mapred.JobClient: Task Id : attempt_201401302213_0004_r_000000_0, Status : FAILED
  java.lang.IllegalArgumentException: Input Iterator not markable
      at org.apache.hadoop.mapreduce.MarkableIterator.&lt;init&gt;(MarkableIterator.java:45)
      at com.nileshc.graphfu.pagerank.Driver$MyReducer.reduce(Driver.java:185)
      at com.nileshc.graphfu.pagerank.Driver$MyReducer.reduce(Driver.java:95)
      at org.apache.hadoop.mapreduce.Reducer.run(Reducer.java:164)
      at org.apache.hadoop.mapred.ReduceTask.runNewReducer(ReduceTask.java:610)
      at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:444)
      at org.apache.hadoop.mapred.Child$4.run(Child.java:268)
      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:1408)
      at org.apache.hadoop.mapred.Child.main(Child.java:262)
  
  attempt_201401302213_0004_r_000000_0: SLF4J: Class path contains multiple SLF4J bindings.
  attempt_201401302213_0004_r_000000_0: SLF4J: Found binding in [jar:file:/hadoop2/share/hadoop/mapreduce1/lib/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
  attempt_201401302213_0004_r_000000_0: SLF4J: Found binding in [jar:file:/hadoop2/share/hadoop/common/lib/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
  attempt_201401302213_0004_r_000000_0: SLF4J: Found binding in [jar:file:/tmp/hadoop/mapred/local/taskTracker/hadoop/jobcache/job_201401302213_0004/jars/job.jar!/org/slf4j/impl/StaticLoggerBinder.class]
  attempt_201401302213_0004_r_000000_0: SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
  14/01/31 00:31:56 INFO mapred.JobClient: Task Id : attempt_201401302213_0004_r_000001_0, Status : FAILED
  java.lang.IllegalArgumentException: Input Iterator not markable
      at org.apache.hadoop.mapreduce.MarkableIterator.&lt;init&gt;(MarkableIterator.java:45)
      at com.nileshc.graphfu.pagerank.Driver$MyReducer.reduce(Driver.java:185)
      at com.nileshc.graphfu.pagerank.Driver$MyReducer.reduce(Driver.java:95)
      at org.apache.hadoop.mapreduce.Reducer.run(Reducer.java:164)
      at org.apache.hadoop.mapred.ReduceTask.runNewReducer(ReduceTask.java:610)
      at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:444)
      at org.apache.hadoop.mapred.Child$4.run(Child.java:268)
      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:1408)
      at org.apache.hadoop.mapred.Child.main(Child.java:262)
  
  attempt_201401302213_0004_r_000001_0: SLF4J: Class path contains multiple SLF4J bindings.
  attempt_201401302213_0004_r_000001_0: SLF4J: Found binding in [jar:file:/hadoop2/share/hadoop/mapreduce1/lib/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
  attempt_201401302213_0004_r_000001_0: SLF4J: Found binding in [jar:file:/hadoop2/share/hadoop/common/lib/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
  attempt_201401302213_0004_r_000001_0: SLF4J: Found binding in [jar:file:/tmp/hadoop/mapred/local/taskTracker/hadoop/jobcache/job_201401302213_0004/jars/job.jar!/org/slf4j/impl/StaticLoggerBinder.class]
  attempt_201401302213_0004_r_000001_0: SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
  14/01/31 00:31:57 INFO mapred.JobClient:  map 100% reduce 0%
  ...
  ...
  ^C^C^C
  </code></pre>
  
  <p><strong>Hadoop distribution details:</strong>
  Hadoop: 2.0.0-mr1-cdh4.5.0 (from CDH4 Tarball 2.0.0-cdh4.5.0)<br/>
  Output of bin/hadoop version:</p>
  
  <pre><code>Hadoop 2.0.0-mr1-cdh4.5.0
  Subversion file:///var/lib/jenkins/workspace/CDH4.5.0-Packaging-Hadoop/build/cdh4/hadoop/2.0.0-cdh4.5.0/source/hadoop-mapreduce1-project -r Unknown
  Compiled by jenkins on Wed Nov 20 14:55:43 PST 2013
  From source with checksum 999ab1ceefbade5990db1ff9ce20057b
  This command was run using /hadoop2/share/hadoop/mapreduce1/lib/hadoop-common-2.0.0-cdh4.5.0.jar
  </code></pre>