/* (c) 2014 LinkedIn Corp. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use * this file except in compliance with the License. You may obtain a copy of the * License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. */ package com.linkedin.cubert.io; import java.io.IOException; import java.io.InputStream; import org.apache.hadoop.io.BooleanWritable; import org.apache.hadoop.io.ByteWritable; import org.apache.hadoop.io.DoubleWritable; import org.apache.hadoop.io.FloatWritable; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.io.Writable; import org.apache.hadoop.io.WritableComparable; import org.apache.hadoop.io.serializer.Deserializer; import org.apache.pig.data.Tuple; import org.apache.pig.data.TupleFactory; import com.linkedin.cubert.block.BlockSchema; import com.linkedin.cubert.block.ColumnType; import com.linkedin.cubert.block.DataType; public class CompactWritablesDeserializer<K> implements Deserializer<K> { private InputStream in; private final DataType[] datatypes; private final Writable[] writables; private byte[] buffer = new byte[32]; public CompactWritablesDeserializer(BlockSchema schema) { if (!schema.isFlatSchema()) throw new IllegalArgumentException("CompactWritablesDeserializer can be used with flat tuple schema only"); datatypes = new DataType[schema.getNumColumns()]; writables = new Writable[schema.getNumColumns()]; for (int i = 0; i < datatypes.length; i++) { ColumnType ctype = schema.getColumnType(i); datatypes[i] = ctype.getType(); writables[i] = createWritable(datatypes[i]); } } @Override public void open(InputStream in) throws IOException { this.in = in; } private static final WritableComparable<?> createWritable(DataType type) { switch (type) { case BOOLEAN: return new BooleanWritable(); case BYTE: return new ByteWritable(); case INT: return new IntWritable(); case LONG: return new LongWritable(); case FLOAT: return new FloatWritable(); case DOUBLE: return new DoubleWritable(); case STRING: return new Text(); default: return null; } } @SuppressWarnings("unchecked") @Override public K deserialize(K object) throws IOException { if (in.available() == 0) throw new IOException(); Tuple t = (Tuple) object; if (t == null) { t = TupleFactory.getInstance().newTuple(datatypes.length); } for (int i = 0; i < datatypes.length; i++) { Object field = null; switch (datatypes[i]) { case BOOLEAN: { IntWritable iw = VariableLengthEncoder.decodeInteger(in); if (iw != null) { ((BooleanWritable) writables[i]).set(iw.get() == 1); field = writables[i]; } break; } case BYTE: { IntWritable iw = VariableLengthEncoder.decodeInteger(in); if (iw != null) { ((ByteWritable) writables[i]).set((byte) iw.get()); field = writables[i]; } break; } case DOUBLE: { DoubleWritable dw = VariableLengthEncoder.decodeDouble(in); if (dw != null) { ((DoubleWritable) writables[i]).set(dw.get()); field = writables[i]; } break; } case FLOAT: { FloatWritable fw = VariableLengthEncoder.decodeFloat(in); if (fw != null) { ((FloatWritable) writables[i]).set(fw.get()); field = writables[i]; } break; } case INT: { IntWritable iw = VariableLengthEncoder.decodeInteger(in); if (iw != null) { ((IntWritable) writables[i]).set(iw.get()); field = writables[i]; } break; } case LONG: { LongWritable lw = VariableLengthEncoder.decodeLong(in); if (lw != null) { ((LongWritable) writables[i]).set(lw.get()); field = writables[i]; } break; } case STRING: { IntWritable iw = VariableLengthEncoder.decodeInteger(in); if (iw != null) { int length = iw.get(); if (length > buffer.length) buffer = new byte[2 * buffer.length]; in.read(buffer, 0, length); ((Text) writables[i]).set(new String(buffer, 0, length)); field = writables[i]; } break; } default: throw new RuntimeException("Cannot deserialize column of type " + datatypes[i]); } t.set(i, field); } return (K) t; } @Override public void close() throws IOException { // TODO Auto-generated method stub } }