co.cask.cdap.data.stream.decoder.BytesStreamEventDecoder.java Source code

Java tutorial

Introduction

Here is the source code for co.cask.cdap.data.stream.decoder.BytesStreamEventDecoder.java

Source

/*
 * Copyright  2014 Cask Data, Inc.
 *
 * 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. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package co.cask.cdap.data.stream.decoder;

import co.cask.cdap.api.flow.flowlet.StreamEvent;
import co.cask.cdap.api.stream.StreamEventDecoder;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.LongWritable;

import java.nio.ByteBuffer;

/**
 * A {@link StreamEventDecoder} that decodes {@link StreamEvent} into {@link LongWritable} as key
 * and {@link BytesWritable} as value for Mapper input. The key carries the event timestamp, while
 * the value is the stream event body.
 */
public final class BytesStreamEventDecoder implements StreamEventDecoder<LongWritable, BytesWritable> {

    private final LongWritable key = new LongWritable();
    private BytesWritable value = new BytesWritable();

    @Override
    public DecodeResult<LongWritable, BytesWritable> decode(StreamEvent event,
            DecodeResult<LongWritable, BytesWritable> result) {
        key.set(event.getTimestamp());
        value = getEventBody(event, value);
        return result.setKey(key).setValue(value);
    }

    private BytesWritable getEventBody(StreamEvent event, BytesWritable result) {
        ByteBuffer body = event.getBody();
        if (body.hasArray()) {
            // If the ByteBuffer is backed by an array, which is exactly the same as exposed by the ByteBuffer
            // simply use the back array. No copying is needed (because read from stream->mapper is synchronous).
            // Creating a new BytesWritable is more efficient as it doesn't need to do array copy,
            // which BytesWritable.set() does.
            if (body.array().length == body.remaining()) {
                return new BytesWritable(body.array());
            }
            // Otherwise, need to copy the byte[], done by the BytesWritable.set() method
            result.set(body.array(), body.arrayOffset() + body.position(), body.remaining());
            return result;
        }

        // Otherwise, need to copy to a new array
        byte[] copy = new byte[body.remaining()];
        body.mark();
        body.get(copy);
        body.reset();
        return new BytesWritable(copy);
    }
}