/* * Copyright MapR Technologies, $year * * 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 com.mapr.storm.streamparser; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import backtype.storm.tuple.Values; /** * * This StreamParser is expecting a format of [size_of_record][content] * that is repeated for each record. * * - size_of_record is a 4-byte encoded integer * - content is a (size_of_record)-long byte array * */ public class CountBlobStreamParser extends StreamParser { private final Logger log = LoggerFactory.getLogger(CountBlobStreamParser.class); private BufferedInputStream buf; private byte[] recordSizeBuffer = new byte[4]; private byte[] recordBuffer; private int recordSize = 0; private long currentOffset = 0; private long currentBeginOffset = 0; private int readSize; private static final int RECORD_SIZE_BYTES = 4; // length of int in bytes public CountBlobStreamParser(FileInputStream in) { buf = new BufferedInputStream(in); recordSizeBuffer = new byte[4]; currentOffset = 0; currentBeginOffset = 0; } @Override public long currentOffset() { return currentOffset; } @Override public List<Object> nextRecord() { List<Object> ret = null; try { while( buf.available() > 0 ) { if( currentOffset == currentBeginOffset ) { // we're at beginning, so start a new record startNewRecord(); } // now try to read record content readContent(); // enough to return record? if( (currentOffset - currentBeginOffset) == recordSize ) { // we have exactly right amount of bytes, so return it currentBeginOffset = currentOffset; return new Values(recordBuffer); } } } catch (IOException e) { e.printStackTrace(); } return ret; } public long getCurrentBeginOffset() { return currentBeginOffset; } /* * private methods */ private void startNewRecord() throws IOException { if( buf.read(recordSizeBuffer) == RECORD_SIZE_BYTES ) { recordSize = getInt(recordSizeBuffer); recordBuffer = new byte[recordSize]; currentOffset += RECORD_SIZE_BYTES; currentBeginOffset = currentOffset; } } private void readContent() throws IOException { readSize = recordSize - (int)(currentOffset-currentBeginOffset); int read = buf.read(recordBuffer, 0, readSize); currentOffset += read; } // get the int value of a byte array private int getInt(byte[] buf) { ByteBuffer bb = ByteBuffer.wrap(buf); return bb.getInt(); } }