1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.io;
20
21 import java.io.DataInput;
22 import java.io.DataOutput;
23 import java.io.IOException;
24 import java.lang.reflect.Array;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.HashMap;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.hadoop.conf.Configurable;
35 import org.apache.hadoop.conf.Configuration;
36 import org.apache.hadoop.conf.Configured;
37 import org.apache.hadoop.hbase.ClusterStatus;
38 import org.apache.hadoop.hbase.HColumnDescriptor;
39 import org.apache.hadoop.hbase.HConstants;
40 import org.apache.hadoop.hbase.HMsg;
41 import org.apache.hadoop.hbase.HRegionInfo;
42 import org.apache.hadoop.hbase.HServerAddress;
43 import org.apache.hadoop.hbase.HServerInfo;
44 import org.apache.hadoop.hbase.HTableDescriptor;
45 import org.apache.hadoop.hbase.KeyValue;
46 import org.apache.hadoop.hbase.client.Delete;
47 import org.apache.hadoop.hbase.client.Get;
48 import org.apache.hadoop.hbase.client.Put;
49 import org.apache.hadoop.hbase.client.Result;
50 import org.apache.hadoop.hbase.client.Scan;
51 import org.apache.hadoop.hbase.client.MultiPutResponse;
52 import org.apache.hadoop.hbase.client.MultiPut;
53 import org.apache.hadoop.hbase.filter.*;
54 import org.apache.hadoop.hbase.io.HbaseMapWritable;
55 import org.apache.hadoop.io.MapWritable;
56 import org.apache.hadoop.io.ObjectWritable;
57 import org.apache.hadoop.io.Text;
58 import org.apache.hadoop.io.Writable;
59 import org.apache.hadoop.io.WritableFactories;
60 import org.apache.hadoop.hbase.regionserver.HRegion;
61 import org.apache.hadoop.hbase.regionserver.wal.HLog;
62 import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
63 import org.apache.hadoop.hbase.util.Bytes;
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 public class HbaseObjectWritable implements Writable, Configurable {
81 protected final static Log LOG = LogFactory.getLog(HbaseObjectWritable.class);
82
83
84
85
86 static final Map<Byte, Class<?>> CODE_TO_CLASS =
87 new HashMap<Byte, Class<?>>();
88 static final Map<Class<?>, Byte> CLASS_TO_CODE =
89 new HashMap<Class<?>, Byte>();
90
91
92 private static final byte NOT_ENCODED = 0;
93 static {
94 byte code = NOT_ENCODED + 1;
95
96 addToMap(Boolean.TYPE, code++);
97 addToMap(Byte.TYPE, code++);
98 addToMap(Character.TYPE, code++);
99 addToMap(Short.TYPE, code++);
100 addToMap(Integer.TYPE, code++);
101 addToMap(Long.TYPE, code++);
102 addToMap(Float.TYPE, code++);
103 addToMap(Double.TYPE, code++);
104 addToMap(Void.TYPE, code++);
105
106
107 addToMap(String.class, code++);
108 addToMap(byte [].class, code++);
109 addToMap(byte [][].class, code++);
110
111
112 addToMap(Text.class, code++);
113 addToMap(Writable.class, code++);
114 addToMap(Writable [].class, code++);
115 addToMap(HbaseMapWritable.class, code++);
116 addToMap(NullInstance.class, code++);
117
118
119 addToMap(HColumnDescriptor.class, code++);
120 addToMap(HConstants.Modify.class, code++);
121 addToMap(HMsg.class, code++);
122 addToMap(HMsg[].class, code++);
123 addToMap(HRegion.class, code++);
124 addToMap(HRegion[].class, code++);
125 addToMap(HRegionInfo.class, code++);
126 addToMap(HRegionInfo[].class, code++);
127 addToMap(HServerAddress.class, code++);
128 addToMap(HServerInfo.class, code++);
129 addToMap(HTableDescriptor.class, code++);
130 addToMap(MapWritable.class, code++);
131
132
133
134
135 addToMap(ClusterStatus.class, code++);
136 addToMap(Delete.class, code++);
137 addToMap(Get.class, code++);
138 addToMap(KeyValue.class, code++);
139 addToMap(KeyValue[].class, code++);
140 addToMap(Put.class, code++);
141 addToMap(Put[].class, code++);
142 addToMap(Result.class, code++);
143 addToMap(Result[].class, code++);
144 addToMap(Scan.class, code++);
145
146 addToMap(WhileMatchFilter.class, code++);
147 addToMap(PrefixFilter.class, code++);
148 addToMap(PageFilter.class, code++);
149 addToMap(InclusiveStopFilter.class, code++);
150 addToMap(ColumnCountGetFilter.class, code++);
151 addToMap(SingleColumnValueFilter.class, code++);
152 addToMap(SingleColumnValueExcludeFilter.class, code++);
153 addToMap(BinaryComparator.class, code++);
154 addToMap(CompareFilter.class, code++);
155 addToMap(RowFilter.class, code++);
156 addToMap(ValueFilter.class, code++);
157 addToMap(QualifierFilter.class, code++);
158 addToMap(SkipFilter.class, code++);
159 addToMap(WritableByteArrayComparable.class, code++);
160 addToMap(FirstKeyOnlyFilter.class, code++);
161 addToMap(DependentColumnFilter.class, code++);
162
163 addToMap(Delete [].class, code++);
164
165 addToMap(MultiPut.class, code++);
166 addToMap(MultiPutResponse.class, code++);
167
168 addToMap(HLog.Entry.class, code++);
169 addToMap(HLog.Entry[].class, code++);
170 addToMap(HLogKey.class, code++);
171
172
173 addToMap(List.class, code++);
174 }
175
176 private Class<?> declaredClass;
177 private Object instance;
178 private Configuration conf;
179
180
181 public HbaseObjectWritable() {
182 super();
183 }
184
185
186
187
188 public HbaseObjectWritable(Object instance) {
189 set(instance);
190 }
191
192
193
194
195
196 public HbaseObjectWritable(Class<?> declaredClass, Object instance) {
197 this.declaredClass = declaredClass;
198 this.instance = instance;
199 }
200
201
202 public Object get() { return instance; }
203
204
205 public Class<?> getDeclaredClass() { return declaredClass; }
206
207
208
209
210
211 public void set(Object instance) {
212 this.declaredClass = instance.getClass();
213 this.instance = instance;
214 }
215
216
217
218
219 @Override
220 public String toString() {
221 return "OW[class=" + declaredClass + ",value=" + instance + "]";
222 }
223
224
225 public void readFields(DataInput in) throws IOException {
226 readObject(in, this, this.conf);
227 }
228
229 public void write(DataOutput out) throws IOException {
230 writeObject(out, instance, declaredClass, conf);
231 }
232
233 private static class NullInstance extends Configured implements Writable {
234 Class<?> declaredClass;
235
236 @SuppressWarnings("unused")
237 public NullInstance() { super(null); }
238
239
240
241
242
243 public NullInstance(Class<?> declaredClass, Configuration conf) {
244 super(conf);
245 this.declaredClass = declaredClass;
246 }
247
248 public void readFields(DataInput in) throws IOException {
249 this.declaredClass = CODE_TO_CLASS.get(in.readByte());
250 }
251
252 public void write(DataOutput out) throws IOException {
253 writeClassCode(out, this.declaredClass);
254 }
255 }
256
257
258
259
260
261
262
263 static void writeClassCode(final DataOutput out, final Class<?> c)
264 throws IOException {
265 Byte code = CLASS_TO_CODE.get(c);
266 if (code == null ) {
267 if ( List.class.isAssignableFrom(c)) {
268 code = CLASS_TO_CODE.get(List.class);
269 }
270 }
271 if (code == null) {
272 LOG.error("Unsupported type " + c);
273 StackTraceElement[] els = new Exception().getStackTrace();
274 for(StackTraceElement elem : els) {
275 LOG.error(elem.getMethodName());
276 }
277
278
279 throw new UnsupportedOperationException("No code for unexpected " + c);
280 }
281 out.writeByte(code);
282 }
283
284
285
286
287
288
289
290
291
292
293 @SuppressWarnings("unchecked")
294 public static void writeObject(DataOutput out, Object instance,
295 Class declaredClass,
296 Configuration conf)
297 throws IOException {
298
299 Object instanceObj = instance;
300 Class declClass = declaredClass;
301
302 if (instanceObj == null) {
303 instanceObj = new NullInstance(declClass, conf);
304 declClass = Writable.class;
305 }
306 writeClassCode(out, declClass);
307 if (declClass.isArray()) {
308
309
310 if (declClass.equals(byte [].class)) {
311 Bytes.writeByteArray(out, (byte [])instanceObj);
312 } else if(declClass.equals(Result [].class)) {
313 Result.writeArray(out, (Result [])instanceObj);
314 } else {
315 int length = Array.getLength(instanceObj);
316 out.writeInt(length);
317 for (int i = 0; i < length; i++) {
318 writeObject(out, Array.get(instanceObj, i),
319 declClass.getComponentType(), conf);
320 }
321 }
322 } else if (List.class.isAssignableFrom(declClass)) {
323 List list = (List)instanceObj;
324 int length = list.size();
325 out.writeInt(length);
326 for (int i = 0; i < length; i++) {
327 writeObject(out, list.get(i),
328 list.get(i).getClass(), conf);
329 }
330 } else if (declClass == String.class) {
331 Text.writeString(out, (String)instanceObj);
332 } else if (declClass.isPrimitive()) {
333 if (declClass == Boolean.TYPE) {
334 out.writeBoolean(((Boolean)instanceObj).booleanValue());
335 } else if (declClass == Character.TYPE) {
336 out.writeChar(((Character)instanceObj).charValue());
337 } else if (declClass == Byte.TYPE) {
338 out.writeByte(((Byte)instanceObj).byteValue());
339 } else if (declClass == Short.TYPE) {
340 out.writeShort(((Short)instanceObj).shortValue());
341 } else if (declClass == Integer.TYPE) {
342 out.writeInt(((Integer)instanceObj).intValue());
343 } else if (declClass == Long.TYPE) {
344 out.writeLong(((Long)instanceObj).longValue());
345 } else if (declClass == Float.TYPE) {
346 out.writeFloat(((Float)instanceObj).floatValue());
347 } else if (declClass == Double.TYPE) {
348 out.writeDouble(((Double)instanceObj).doubleValue());
349 } else if (declClass == Void.TYPE) {
350 } else {
351 throw new IllegalArgumentException("Not a primitive: "+declClass);
352 }
353 } else if (declClass.isEnum()) {
354 Text.writeString(out, ((Enum)instanceObj).name());
355 } else if (Writable.class.isAssignableFrom(declClass)) {
356 Class <?> c = instanceObj.getClass();
357 Byte code = CLASS_TO_CODE.get(c);
358 if (code == null) {
359 out.writeByte(NOT_ENCODED);
360 Text.writeString(out, c.getName());
361 } else {
362 writeClassCode(out, c);
363 }
364 ((Writable)instanceObj).write(out);
365 } else {
366 throw new IOException("Can't write: "+instanceObj+" as "+declClass);
367 }
368 }
369
370
371
372
373
374
375
376
377
378
379 public static Object readObject(DataInput in, Configuration conf)
380 throws IOException {
381 return readObject(in, null, conf);
382 }
383
384
385
386
387
388
389
390
391
392
393 @SuppressWarnings("unchecked")
394 public static Object readObject(DataInput in,
395 HbaseObjectWritable objectWritable, Configuration conf)
396 throws IOException {
397 Class<?> declaredClass = CODE_TO_CLASS.get(in.readByte());
398 Object instance;
399 if (declaredClass.isPrimitive()) {
400 if (declaredClass == Boolean.TYPE) {
401 instance = Boolean.valueOf(in.readBoolean());
402 } else if (declaredClass == Character.TYPE) {
403 instance = Character.valueOf(in.readChar());
404 } else if (declaredClass == Byte.TYPE) {
405 instance = Byte.valueOf(in.readByte());
406 } else if (declaredClass == Short.TYPE) {
407 instance = Short.valueOf(in.readShort());
408 } else if (declaredClass == Integer.TYPE) {
409 instance = Integer.valueOf(in.readInt());
410 } else if (declaredClass == Long.TYPE) {
411 instance = Long.valueOf(in.readLong());
412 } else if (declaredClass == Float.TYPE) {
413 instance = Float.valueOf(in.readFloat());
414 } else if (declaredClass == Double.TYPE) {
415 instance = Double.valueOf(in.readDouble());
416 } else if (declaredClass == Void.TYPE) {
417 instance = null;
418 } else {
419 throw new IllegalArgumentException("Not a primitive: "+declaredClass);
420 }
421 } else if (declaredClass.isArray()) {
422 if (declaredClass.equals(byte [].class)) {
423 instance = Bytes.readByteArray(in);
424 } else if(declaredClass.equals(Result [].class)) {
425 instance = Result.readArray(in);
426 } else {
427 int length = in.readInt();
428 instance = Array.newInstance(declaredClass.getComponentType(), length);
429 for (int i = 0; i < length; i++) {
430 Array.set(instance, i, readObject(in, conf));
431 }
432 }
433 } else if (List.class.isAssignableFrom(declaredClass)) {
434 int length = in.readInt();
435 instance = new ArrayList(length);
436 for (int i = 0; i < length; i++) {
437 ((ArrayList)instance).add(readObject(in, conf));
438 }
439 } else if (declaredClass == String.class) {
440 instance = Text.readString(in);
441 } else if (declaredClass.isEnum()) {
442 instance = Enum.valueOf((Class<? extends Enum>) declaredClass,
443 Text.readString(in));
444 } else {
445 Class instanceClass = null;
446 Byte b = in.readByte();
447 if (b.byteValue() == NOT_ENCODED) {
448 String className = Text.readString(in);
449 try {
450 instanceClass = getClassByName(conf, className);
451 } catch (ClassNotFoundException e) {
452 throw new RuntimeException("Can't find class " + className);
453 }
454 } else {
455 instanceClass = CODE_TO_CLASS.get(b);
456 }
457 Writable writable = WritableFactories.newInstance(instanceClass, conf);
458 writable.readFields(in);
459 instance = writable;
460 if (instanceClass == NullInstance.class) {
461 declaredClass = ((NullInstance)instance).declaredClass;
462 instance = null;
463 }
464 }
465 if (objectWritable != null) {
466 objectWritable.declaredClass = declaredClass;
467 objectWritable.instance = instance;
468 }
469 return instance;
470 }
471
472 @SuppressWarnings("unchecked")
473 private static Class getClassByName(Configuration conf, String className)
474 throws ClassNotFoundException {
475 if(conf != null) {
476 return conf.getClassByName(className);
477 }
478 ClassLoader cl = Thread.currentThread().getContextClassLoader();
479 if(cl == null) {
480 cl = HbaseObjectWritable.class.getClassLoader();
481 }
482 return Class.forName(className, true, cl);
483 }
484
485 private static void addToMap(final Class<?> clazz, final byte code) {
486 CLASS_TO_CODE.put(clazz, code);
487 CODE_TO_CLASS.put(code, clazz);
488 }
489
490 public void setConf(Configuration conf) {
491 this.conf = conf;
492 }
493
494 public Configuration getConf() {
495 return this.conf;
496 }
497 }