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, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package org.apache.hadoop.mapred.join; 020 021 import java.io.IOException; 022 023 import org.apache.hadoop.classification.InterfaceAudience; 024 import org.apache.hadoop.classification.InterfaceStability; 025 import org.apache.hadoop.io.Writable; 026 import org.apache.hadoop.io.WritableComparable; 027 import org.apache.hadoop.io.WritableComparator; 028 import org.apache.hadoop.io.WritableUtils; 029 import org.apache.hadoop.mapred.RecordReader; 030 031 /** 032 * Proxy class for a RecordReader participating in the join framework. 033 * This class keeps track of the "head" key-value pair for the 034 * provided RecordReader and keeps a store of values matching a key when 035 * this source is participating in a join. 036 * @deprecated Use 037 * {@link org.apache.hadoop.mapreduce.lib.join.WrappedRecordReader} instead 038 */ 039 @Deprecated 040 @InterfaceAudience.Public 041 @InterfaceStability.Stable 042 public class WrappedRecordReader<K extends WritableComparable, 043 U extends Writable> 044 implements ComposableRecordReader<K,U> { 045 046 private boolean empty = false; 047 private RecordReader<K,U> rr; 048 private int id; // index at which values will be inserted in collector 049 050 private K khead; // key at the top of this RR 051 private U vhead; // value assoc with khead 052 private WritableComparator cmp; 053 054 private ResetableIterator<U> vjoin; 055 056 /** 057 * For a given RecordReader rr, occupy position id in collector. 058 */ 059 WrappedRecordReader(int id, RecordReader<K,U> rr, 060 Class<? extends WritableComparator> cmpcl) throws IOException { 061 this.id = id; 062 this.rr = rr; 063 khead = rr.createKey(); 064 vhead = rr.createValue(); 065 try { 066 cmp = (null == cmpcl) 067 ? WritableComparator.get(khead.getClass()) 068 : cmpcl.newInstance(); 069 } catch (InstantiationException e) { 070 throw (IOException)new IOException().initCause(e); 071 } catch (IllegalAccessException e) { 072 throw (IOException)new IOException().initCause(e); 073 } 074 vjoin = new StreamBackedIterator<U>(); 075 next(); 076 } 077 078 /** {@inheritDoc} */ 079 public int id() { 080 return id; 081 } 082 083 /** 084 * Return the key at the head of this RR. 085 */ 086 public K key() { 087 return khead; 088 } 089 090 /** 091 * Clone the key at the head of this RR into the object supplied. 092 */ 093 public void key(K qkey) throws IOException { 094 WritableUtils.cloneInto(qkey, khead); 095 } 096 097 /** 098 * Return true if the RR- including the k,v pair stored in this object- 099 * is exhausted. 100 */ 101 public boolean hasNext() { 102 return !empty; 103 } 104 105 /** 106 * Skip key-value pairs with keys less than or equal to the key provided. 107 */ 108 public void skip(K key) throws IOException { 109 if (hasNext()) { 110 while (cmp.compare(khead, key) <= 0 && next()); 111 } 112 } 113 114 /** 115 * Read the next k,v pair into the head of this object; return true iff 116 * the RR and this are exhausted. 117 */ 118 protected boolean next() throws IOException { 119 empty = !rr.next(khead, vhead); 120 return hasNext(); 121 } 122 123 /** 124 * Add an iterator to the collector at the position occupied by this 125 * RecordReader over the values in this stream paired with the key 126 * provided (ie register a stream of values from this source matching K 127 * with a collector). 128 */ 129 // JoinCollector comes from parent, which has 130 @SuppressWarnings("unchecked") // no static type for the slot this sits in 131 public void accept(CompositeRecordReader.JoinCollector i, K key) 132 throws IOException { 133 vjoin.clear(); 134 if (0 == cmp.compare(key, khead)) { 135 do { 136 vjoin.add(vhead); 137 } while (next() && 0 == cmp.compare(key, khead)); 138 } 139 i.add(id, vjoin); 140 } 141 142 /** 143 * Write key-value pair at the head of this stream to the objects provided; 144 * get next key-value pair from proxied RR. 145 */ 146 public boolean next(K key, U value) throws IOException { 147 if (hasNext()) { 148 WritableUtils.cloneInto(key, khead); 149 WritableUtils.cloneInto(value, vhead); 150 next(); 151 return true; 152 } 153 return false; 154 } 155 156 /** 157 * Request new key from proxied RR. 158 */ 159 public K createKey() { 160 return rr.createKey(); 161 } 162 163 /** 164 * Request new value from proxied RR. 165 */ 166 public U createValue() { 167 return rr.createValue(); 168 } 169 170 /** 171 * Request progress from proxied RR. 172 */ 173 public float getProgress() throws IOException { 174 return rr.getProgress(); 175 } 176 177 /** 178 * Request position from proxied RR. 179 */ 180 public long getPos() throws IOException { 181 return rr.getPos(); 182 } 183 184 /** 185 * Forward close request to proxied RR. 186 */ 187 public void close() throws IOException { 188 rr.close(); 189 } 190 191 /** 192 * Implement Comparable contract (compare key at head of proxied RR 193 * with that of another). 194 */ 195 public int compareTo(ComposableRecordReader<K,?> other) { 196 return cmp.compare(key(), other.key()); 197 } 198 199 /** 200 * Return true iff compareTo(other) retn true. 201 */ 202 @SuppressWarnings("unchecked") // Explicit type check prior to cast 203 public boolean equals(Object other) { 204 return other instanceof ComposableRecordReader 205 && 0 == compareTo((ComposableRecordReader)other); 206 } 207 208 public int hashCode() { 209 assert false : "hashCode not designed"; 210 return 42; 211 } 212 213 }