All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.aliyun.openservices.ots.internal.writer.RowChangeEventHandler Maven / Gradle / Ivy

package com.aliyun.openservices.ots.internal.writer;

import com.aliyun.openservices.ots.ClientException;
import com.aliyun.openservices.ots.OTSAsync;
import com.aliyun.openservices.ots.OTSException;
import com.aliyun.openservices.ots.internal.OTSCallback;
import com.aliyun.openservices.ots.model.*;
import com.lmax.disruptor.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class RowChangeEventHandler implements EventHandler {
    private Logger logger = LoggerFactory.getLogger(RowChangeEventHandler.class);

    private OTSAsync ots;
    private WriteRPCBuffer buffer;
    private int concurrency;
    private Semaphore semaphore;
    private OTSCallback callback;
    private Executor executor;
    private AtomicLong totalRequestCount;

    public RowChangeEventHandler(OTSAsync ots, WriterConfig writerConfig, OTSCallback callback, Executor executor) {
        this.ots = ots;
        this.buffer = new WriteRPCBuffer(writerConfig);
        this.concurrency = writerConfig.getConcurrency();
        this.semaphore = new Semaphore(concurrency);
        this.callback = callback;
        this.executor = executor;
        this.totalRequestCount = new AtomicLong();
    }

    @Override
    public void onEvent(RowChangeEvent rowChangeEvent, long sequence, boolean endOfBatch) throws Exception {
        BatchWriteRowRequest request = null;

        boolean shouldWaitFlush = false;
        ReentrantLock lock = null;
        Condition flushCond = null;

        if (rowChangeEvent.type == RowChangeEvent.EventType.FLUSH) {
            logger.debug("FlushSignal with QueueSize: {}", buffer.getTotalRowsCount());
            if (buffer.getTotalRowsCount() > 0) {
                request = buffer.makeRequest();
                buffer.clear();
            }

            shouldWaitFlush = true;
            lock = rowChangeEvent.lock;
            flushCond = rowChangeEvent.condition;
        } else {
            final RowChange rowChange = rowChangeEvent.rowChange;
            boolean succeed = buffer.appendRowChange(rowChange);
            if (!succeed) {
                request = buffer.makeRequest();
                buffer.clear();
                succeed = buffer.appendRowChange(rowChange);

                if (!succeed) {
                    executor.execute(new Runnable() {
                        @Override
                        public void run() {
                            callback.onFailed(new OTSContext(rowChange, null),
                                    new ClientException("Can not even append only one row into buffer."));
                        }
                    });
                }
            }
        }

        if (request != null) {
            // send this request
            semaphore.acquire();
            logger.debug("Acquire semaphore, start send async request.");
            final BatchWriteRowRequest finalRequest = request;
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    totalRequestCount.incrementAndGet();
                    ots.batchWriteRow(finalRequest, new FlushCallback(ots, new AtomicInteger(1), semaphore, callback, executor));
                }
            });
            //ots.batchWriteRow(finalRequest, new FlushCallback(ots, new AtomicInteger(1), semaphore, callback, executor));
        }

        if (shouldWaitFlush) {
            waitFlush();
            lock.lock();
            try {
                flushCond.signal();
            } finally {
                lock.unlock();
            }
        }
    }

    private void waitFlush() throws InterruptedException {
        logger.debug("Wait flush.");
        for (int i = 0; i < concurrency; i++) {
            semaphore.acquire();
            logger.debug("Wait flush: {}, {}", i, concurrency);
        }
        semaphore.release(concurrency);
        logger.debug("Wait flush finished.");
    }

    public long getTotalRPCCount() {
        return totalRequestCount.get();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy