Package com.hmsonline.storm.cassandra.bolt

Source Code of com.hmsonline.storm.cassandra.bolt.AbstractBatchingBolt

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.hmsonline.storm.cassandra.bolt;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hmsonline.storm.cassandra.bolt.mapper.TupleMapper;
import com.hmsonline.storm.cassandra.StormCassandraConstants;

import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.IRichBolt;
import backtype.storm.tuple.Tuple;
import backtype.storm.utils.Utils;

/**
* Abstract <code>IRichBolt</code> implementation that caches/batches
* <code>backtype.storm.tuple.Tuple</code> and processes them on a separate
* thread.
* <p/>
* <p/>
* Subclasses are obligated to implement the
* <code>executeBatch(List<Tuple> inputs)</code> method, called when a batch of
* tuples should be processed.
* <p/>
* Subclasses that overide the <code>prepare()</code> and <code>cleanup()</code>
* methods <b><i>must</i></b> call the corresponding methods on the superclass
* (i.e. <code>super.prepare()</code> and <code>super.cleanup()</code>) to
* ensure proper initialization and termination.
*
*/
@SuppressWarnings("serial")
public abstract class AbstractBatchingBolt<K, C, V> extends CassandraBolt<K, C, V> implements IRichBolt {
    private static final Logger LOG = LoggerFactory.getLogger(AbstractBatchingBolt.class);

    protected AckStrategy ackStrategy = AckStrategy.ACK_IGNORE;

    protected OutputCollector collector;

    protected LinkedBlockingQueue<Tuple> queue;

    private BatchThread batchThread;

    public AbstractBatchingBolt(String clientConfigKey, TupleMapper<K, C, V> tupleMapper) {
        super(clientConfigKey, tupleMapper);
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Override
    public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
        super.prepare(stormConf, context);
        int batchMaxSize = Utils.getInt(Utils.get(stormConf, StormCassandraConstants.CASSANDRA_BATCH_MAX_SIZE, 0));
        this.collector = collector;
        this.queue = new LinkedBlockingQueue<Tuple>();
        this.batchThread = new BatchThread(batchMaxSize);
        this.batchThread.start();
    }

    @Override
    public void execute(Tuple input) {
        if (this.ackStrategy == AckStrategy.ACK_ON_RECEIVE) {
            this.collector.ack(input);
        }
        this.queue.offer(input);
    }

    @Override
    public void cleanup() {
        this.batchThread.stopRunning();
        super.cleanup();
    }

    /**
     * Process a <code>java.util.List</code> of
     * <code>backtype.storm.tuple.Tuple</code> objects that have been
     * cached/batched.
     * <p/>
     * This method is analagous to the <code>execute(Tuple input)</code> method
     * defined in the bolt interface. Subclasses are responsible for processing
     * and/or ack'ing tuples as necessary. The only difference is that tuples
     * are passed in as a list, as opposed to one at a time.
     * <p/>
     *
     *
     * @param inputs
     */
    public abstract void executeBatch(List<Tuple> inputs);

    private class BatchThread extends Thread {

        int batchMaxSize;
        boolean stopRequested = false;

        BatchThread(int batchMaxSize) {
            super("batch-bolt-thread");
            super.setDaemon(true);
            this.batchMaxSize = batchMaxSize;
        }

        @Override
        public void run() {
            while (!stopRequested) {
                try {
                    ArrayList<Tuple> batch = new ArrayList<Tuple>();
                    // drainTo() does not block, take() does.
                    Tuple t = queue.take();
                    batch.add(t);
                    if (batchMaxSize > 0) {
                        queue.drainTo(batch, batchMaxSize);
                    } else {
                        queue.drainTo(batch);
                    }
                    executeBatch(batch);

                } catch (InterruptedException e) {
                    LOG.error("Interupted in batching bolt.", e);
                }
            }
        }

        void stopRunning() {
            this.stopRequested = true;
        }
    }

    public AckStrategy getAckStrategy() {
        return ackStrategy;
    }

    public void setAckStrategy(AckStrategy ackStrategy) {
        this.ackStrategy = ackStrategy;
    }
}
TOP

Related Classes of com.hmsonline.storm.cassandra.bolt.AbstractBatchingBolt

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.