private void addFileToMap(Matcher matcher, Path file, boolean sawBase,
                              Map<Integer, BucketTracker> splitToBucketMap) {
      if (!matcher.find()) {
        String msg = "Found a non-bucket file that we thought matched the bucket pattern! " +
          file.toString() + " Matcher=" + matcher.toString();
        LOG.error(msg);
        //following matcher.group() would fail anyway and we don't want to skip files since that
        //may be a data loss scenario
        throw new IllegalArgumentException(msg);
      }
      int bucketNum = -1;
      Integer attemptId = null;
      if (matcher.groupCount() > 0) {
        bucketNum = Integer.parseInt(matcher.group(1));
        attemptId = matcher.group(2) != null ? Integer.valueOf(matcher.group(2).substring(1)) : null;
      } else {
        bucketNum = Integer.valueOf(matcher.group());
      }

      BucketTracker bt = splitToBucketMap.get(bucketNum);
      if (bt == null) {
        bt = new BucketTracker();
        splitToBucketMap.put(bucketNum, bt);
      }
      LOG.debug("Adding " + file.toString() + " to list of files for splits");
      bt.buckets.add(file);
      bt.sawBase |= sawBase;
      bt.deltasToAttemptId.put(file.getParent().getName(), attemptId);
    }
This input format returns its own input split as a value.  This is because our splits
contain information needed to properly construct the writer.  Crazy, huh?
ql/src/java/org/apache/hadoop/hive/ql/txn/compactor/MRCompactor.java